Bzoj 3110: [Zjoi2013]K大数查询 树套树
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3738 Solved: 1484
[Submit][Status][Discuss]
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操作中c<=Maxlongint
Source
题解:
权值线段树套区间线段树。
数据加强了。。。要开long long。。。c有负数了。。。
离散一下就行了。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 50010 4 #define LL long long 5 struct node 6 { 7 int left,right; 8 LL tag,sum; 9 }tree[MAXN*300]; 10 int n,SIZE,s1[MAXN],s2[MAXN],s3[MAXN],s4[MAXN],cc[MAXN],root[MAXN*5]; 11 int read() 12 { 13 int s=0,fh=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 16 return s*fh; 17 } 18 void Pushup(int k) 19 { 20 int l=tree[k].left,r=tree[k].right; 21 tree[k].sum=tree[l].sum+tree[r].sum; 22 } 23 void Pushdown(int k,int ql,int qr) 24 { 25 if(tree[k].left==0)tree[k].left=++SIZE; 26 if(tree[k].right==0)tree[k].right=++SIZE; 27 int l=tree[k].left,r=tree[k].right; 28 if(tree[k].tag!=0) 29 { 30 tree[l].tag+=tree[k].tag; 31 tree[r].tag+=tree[k].tag; 32 int mid=(ql+qr)/2; 33 tree[l].sum+=(LL)(mid-ql+1)*tree[k].tag; 34 tree[r].sum+=(LL)(qr-mid)*tree[k].tag; 35 tree[k].tag=0; 36 } 37 } 38 void Update2(int &k,int l,int r,int ql,int qr) 39 { 40 if(k==0)k=++SIZE; 41 //if(l==r){tree[k].sum++;return;} 42 if(ql<=l&&r<=qr){tree[k].tag++;tree[k].sum+=(LL)(qr-ql+1);return;} 43 Pushdown(k,l,r); 44 int mid=(l+r)/2; 45 if(qr<=mid)Update2(tree[k].left,l,mid,ql,qr); 46 else if(ql>mid)Update2(tree[k].right,mid+1,r,ql,qr); 47 else {Update2(tree[k].left,l,mid,ql,mid);Update2(tree[k].right,mid+1,r,mid+1,qr);} 48 Pushup(k); 49 } 50 void Update1(int k,int l,int r,int ql,int qr,int K) 51 { 52 Update2(root[k],1,n,ql,qr); 53 if(l==r)return; 54 int mid=(l+r)/2; 55 if(K<=mid)Update1(k*2,l,mid,ql,qr,K); 56 else Update1(k*2+1,mid+1,r,ql,qr,K); 57 //else{Update1(k*2,l,mid,ql,mid,K);Update1(k*2+1,mid+1,r,mid+1,qr,K);} 58 } 59 LL Find2(int k,int l,int r,int ql,int qr) 60 { 61 if(k==0)return 0; 62 if(ql<=l&&r<=qr)return tree[k].sum; 63 Pushdown(k,l,r); 64 int mid=(l+r)/2; 65 if(qr<=mid)return Find2(tree[k].left,l,mid,ql,qr); 66 else if(ql>mid)return Find2(tree[k].right,mid+1,r,ql,qr); 67 else return Find2(tree[k].left,l,mid,ql,mid)+Find2(tree[k].right,mid+1,r,mid+1,qr); 68 } 69 int Find1(int k,int l,int r,int ql,int qr,int K) 70 { 71 LL gs=Find2(root[k*2],1,n,ql,qr); 72 if(l==r)return l; 73 int mid=(l+r)/2; 74 if(K<=gs)return Find1(k*2,l,mid,ql,qr,K); 75 else return Find1(k*2+1,mid+1,r,ql,qr,K-gs); 76 } 77 int main() 78 { 79 int m,lc,tot,i,k; 80 n=read();m=read(); 81 lc=0; 82 for(i=1;i<=m;i++) 83 { 84 s1[i]=read();s2[i]=read();s3[i]=read();s4[i]=read(); 85 if(s1[i]==1)cc[++lc]=s4[i]; 86 } 87 sort(cc+1,cc+lc+1); 88 tot=unique(cc+1,cc+lc+1)-(cc+1); 89 SIZE=0; 90 for(i=1;i<=m;i++) 91 { 92 if(s1[i]==1) 93 { 94 k=lower_bound(cc+1,cc+tot+1,s4[i])-cc; 95 Update1(1,1,tot,s2[i],s3[i],tot-k+1); 96 } 97 else 98 { 99 k=Find1(1,1,tot,s2[i],s3[i],s4[i]); 100 k=tot-k+1; 101 printf("%d\n",cc[k]); 102 } 103 } 104 return 0; 105 }