Bzoj 3110: [Zjoi2013]K大数查询 树套树

3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 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

Sample Output

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 }

 

posted @ 2016-03-27 21:06  微弱的世界  阅读(197)  评论(0编辑  收藏  举报