题
O∧O http://www.lydsy.com/JudgeOnline/problem.php?id=3110
解
首先对输入的操作1的数字c离散化。
然后建一棵线段树,这个线段树中,li=a,ri=b这一位置存放 满足li<=c<=ri的的数字c们所对应线段树
这些内层的线段树是根据区间来构造的,比如对于c∈(x,y)的线段树,在li=a,ri=b的位置记录了区间[a,b]中有多少c∈(x,y)的c。
(思路来自某其他博客)
//http://www.lydsy.com/JudgeOnline/problem.php?id=3110
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=100044;
const int M=N*256;
struct Input
{
int op,a,b,c;
} input[55555];
int mp[N],lmp;
int root[N*4],lc[M],rc[M],lazy[M],tnum;
ll sum[M];
int n,m;
ll count(int id,int li,int ri,int L,int R)
{
if(L<=li && ri<=R)
return sum[id];
ll ret=(min(R,ri)-max(L,li)+1)*lazy[id],mid=(li+ri)>>1;
if(mid>=L)
ret+=count(lc[id],li,mid,L,R);
if(mid+1<=R)
ret+=count(rc[id],mid+1,ri,L,R);
return ret;
}
int query(int L,int R,ll K)
{
int li=1,ri=n,mid,now=1;
ll tmp;
while(li!=ri)
{
mid=(li+ri)>>1;
tmp=count(root[now*2+1],1,n,L,R); //lc: now*2 (li~mid) rc:now*2+1 (mid+1~ri)
if(tmp<K) //in the left part
{
ri=mid;
now=now*2;
K-=tmp;
}
else
{
li=mid+1;
now=now*2+1;
}
}
return li;
}
void modify(int &id,int li,int ri,int L,int R)
{
int mid=(li+ri)>>1;
if(!id) id=++tnum;
if(L<=li && ri<=R)
{
sum[id]+=ri-li+1;
++lazy[id];
return ;
}
if(mid>=L)
modify(lc[id],li,mid,L,R);
if(mid+1<=R)
modify(rc[id],mid+1,ri,L,R);
sum[id]=sum[lc[id]]+sum[rc[id]]+lazy[id]*(ri-li+1);
}
void deal(int L,int R,int num)
{
int li=1,ri=n,mid,now=1;
while(li!=ri)
{
modify(root[now],1,n,L,R);
mid=(li+ri)>>1;
if(mid<num) //choose the right child
{
li=mid+1;
now=now*2+1;
}
else //choose the left child
{
ri=mid;
now=now*2;
}
}
modify(root[now],1,n,L,R);
}
void solve(int op_num)
{
int op,a,b,c,i;
for(i=1;i<=op_num;i++)
{
op=input[i].op; a=input[i].a; b=input[i].b; c=input[i].c;
if(op==1) //update
deal(a,b,c);
else //query
{
int ans=query(a,b,c);
printf("%d\n",mp[ans]);
}
}
}
inline void read(int &ret)
{
int k=0;
char f=1;
char c=getchar();
for(;!isdigit(c);c=getchar() )
if(c=='-')
f=-1;
for(;isdigit(c);c=getchar() )
k=k*10+c-'0';
ret=k*f;
}
void init(int op_num)
{
int i,j;
for(i=1;i<=op_num;i++)
{
read(input[i].op);
read(input[i].a);
read(input[i].b);
read(input[i].c);
}
lmp=0;
for(i=1;i<=op_num;i++)
if(input[i].op==1)
mp[++lmp]=input[i].c;
sort(mp+1,mp+lmp+1);
lmp=unique(mp+1,mp+lmp+1)-(mp+1);
for(i=1;i<=op_num;i++)
if(input[i].op==1)
input[i].c=lower_bound(mp+1,mp+lmp+1,input[i].c)-mp;
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
init(m);
solve(m);
return 0;
}
/*
2 5
1 1 2 -11
1 1 2 -22
2 1 1 2
2 1 1 1
2 1 2 3
*/