【bzoj3110】[Zjoi2013]K大数查询
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中abs(c)<=Maxlongint
一直不是很理解树套树是个什么鬼。
题解告诉我此题为线段树套线段树。一维维护权值,二维维护区间。
精髓还没有领悟到,果真我还是很弱QWQ
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstring> 6 #define ll long long 7 using namespace std; 8 int a,b,c; 9 int n,m,sz; 10 int root[200005]; 11 int ls[20000005],rs[20000005],sum[20000005],lazy[20000005]; 12 void pushdown(int k,int l,int r){ 13 if ((!lazy[k])||l==r) return;//如果没标记或者已经到了底层 14 if (!ls[k])ls[k]=++sz; 15 if (!rs[k])rs[k]=++sz; 16 int mid=(l+r)>>1; 17 lazy[ls[k]]+=lazy[k];lazy[rs[k]]+=lazy[k]; 18 sum[ls[k]]+=(mid-l+1)*lazy[k]; 19 sum[rs[k]]+=(r-mid)*lazy[k]; 20 lazy[k]=0; 21 } 22 23 void modify(int &k,int l,int r,int a,int b){ 24 if (!k)k=++sz; 25 pushdown(k,l,r); 26 if (a==l&&b==r){ 27 lazy[k]++; 28 sum[k]+=(r-l+1); 29 return; 30 } 31 int mid=(l+r)>>1; 32 if (a>mid) modify(rs[k],mid+1,r,a,b); 33 else if (b<=mid) modify(ls[k],l,mid,a,b); 34 else modify(ls[k],l,mid,a,mid),modify(rs[k],mid+1,r,mid+1,b); 35 sum[k]=sum[ls[k]]+sum[rs[k]]; 36 } 37 38 void insert(){ 39 int l=1,r=n,k=1; 40 while (l!=r){ 41 modify(root[k],1,n,a,b); 42 int mid=(l+r)>>1; 43 if (c>mid)l=mid+1,k=k<<1|1; 44 else r=mid,k=k<<1; 45 } 46 modify(root[k],1,n,a,b); 47 } 48 49 int query(int k,int l,int r,int a,int b){ 50 if (!k) return 0; 51 pushdown(k,l,r); 52 if (a==l&&b==r)return sum[k]; 53 int mid=(l+r)>>1; 54 if (a>mid) return query(rs[k],mid+1,r,a,b); 55 else if (b<=mid) return query(ls[k],l,mid,a,b); 56 else return query(ls[k],l,mid,a,mid)+query(rs[k],mid+1,r,mid+1,b); 57 } 58 59 int solve(){ 60 int l=1,r=n,k=1; 61 while (l!=r){ 62 int t=query(root[k<<1],1,n,a,b); 63 int mid=(l+r)>>1; 64 if (t>=c)r=mid,k=k<<1; 65 else l=mid+1,k=k<<1|1,c-=t; 66 } 67 return l; 68 } 69 70 int main(){ 71 freopen("sj.txt","r",stdin); 72 freopen("me.txt","w",stdout); 73 scanf("%d%d",&n,&m); 74 for (int i=1;i<=m;i++){ 75 int f; 76 scanf("%d%d%d%d",&f,&a,&b,&c); 77 if (f==1)c=n-c+1,insert(); 78 else printf("%d\n",n-solve()+1); 79 } 80 }