【bzoj 3110】[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

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。

整体二分裸题……顺便可以了解一下用树状数组实现区间加和区间求和操作。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #define LL long long
 6 using namespace std;
 7 const int N=1e5+5;
 8 int n,m,qid,mx,ans[N];
 9 LL tr[N][2];
10 bool f[N];
11 struct node{int op,l,r,c,id;}a[N],tmp[N];
12 LL read()
13 {
14     LL x=0,f=1;char c=getchar();
15     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
16     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
17     return x*f;
18 }
19 int lowbit(int x){return x&(-x);}
20 void add(int x,LL c,int id){while(x<=n)tr[x][id]+=c,x+=lowbit(x);}
21 void insert(int id,LL c){add(id,c,0);add(id,c*id,1);}
22 LL query(int x,int id){LL ans=0;while(x)ans+=tr[x][id],x-=lowbit(x);return ans;}
23 LL ask(int id){LL ans=(id+1)*query(id,0)-query(id,1);return ans;}
24 void work(int x,int y,int l,int r)
25 {
26     if(l==r){for(int i=x;i<=y;i++)if(a[i].op==2)ans[a[i].id]=l;return;}
27     int h1=x,h2=x,mid=(l+r)>>1;
28     for(int i=x;i<=y;i++)
29         if(a[i].op==2)
30         {
31             LL temp=ask(a[i].r)-ask(a[i].l-1);
32             if(temp<a[i].c)f[i]=false,a[i].c-=temp;
33             else f[i]=true,h2++;
34         }
35         else if(a[i].c<=mid)insert(a[i].l,1),insert(a[i].r+1,-1),f[i]=true,h2++;
36         else f[i]=false;
37     for(int i=x;i<=y;i++)if(a[i].op==1&&a[i].c<=mid)insert(a[i].l,-1),insert(a[i].r+1,1);
38     for(int i=x;i<=y;i++)if(f[i])tmp[h1++]=a[i];else tmp[h2++]=a[i];
39     for(int i=x;i<=y;i++)a[i]=tmp[i];
40     work(x,h1-1,l,mid);work(h1,y,mid+1,r);
41 }
42 int main()
43 {
44     n=read();m=read();
45     for(int i=1;i<=m;i++)
46     {
47         a[i].op=read();a[i].l=read();a[i].r=read();a[i].c=read();
48         if(a[i].op==1)a[i].c=n-a[i].c+1,mx=max(mx,a[i].c);
49         else a[i].id=++qid;
50     }
51     work(1,m,1,mx);
52     for(int i=1;i<=qid;i++)printf("%d
",n-ans[i]+1);
53     return 0;
54 } 
View Code
原文地址:https://www.cnblogs.com/zsnuo/p/8000567.html