整体二分--BZOJ1901: Zju2112 Dynamic Rankings

n<=10000个数有m<=10000个操作,1、询问一个区间的第k小的数;2、单点修改。

带修主席树。

整体二分。

整体二分的必要条件:

这里写图片描述

 1 #include<string.h>
 2 #include<stdlib.h>
 3 #include<stdio.h>
 4 //#include<assert.h>
 5 #include<algorithm>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n,m;
10 #define maxn 30011
11 const int inf=0x3f3f3f3f;
12 struct Ope
13 {
14     int x,y,z,id,type;
15     //type=1: 询问区间[x,y]第z大,询问编号id
16     //type=0:把位置x的数修改为y,增加:z=1,删除:z=-1
17 }q[maxn],al[maxn],ar[maxn];int len;
18 int ans[maxn];
19 
20 struct BIT
21 {
22     int a[maxn];
23     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
24     int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;}
25 }t;
26 
27 void solve(int L,int R,int ql,int qr)
28 {
29     if (L>R || ql>qr) return;
30     if (L==R)
31     {
32         for (int i=ql;i<=qr;i++) if (q[i].type) ans[q[i].id]=L;
33         return;
34     }
35     int mid=(L+R)>>1,lql=0,lqr=0;
36     for (int i=ql;i<=qr;i++)
37     {
38         if (q[i].type)
39         {
40             int tmp=t.query(q[i].y)-t.query(q[i].x-1);
41             if (tmp>=q[i].z) al[++lql]=q[i];
42             else
43             {
44                 q[i].z-=tmp;
45                 ar[++lqr]=q[i];
46             }
47         }
48         else
49         {
50             if (q[i].y<=mid)
51             {
52                 t.add(q[i].x,q[i].z);
53                 al[++lql]=q[i];
54             }
55             else ar[++lqr]=q[i];
56         }
57     }
58     for (int i=1;i<=lql;i++) if (al[i].type==0) t.add(al[i].x,-al[i].z);
59     for (int i=1,j=ql;i<=lql;i++,j++) q[j]=al[i];
60     for (int i=1,j=ql+lql;i<=lqr;i++,j++) q[j]=ar[i];
61     solve(L,mid,ql,ql+lql-1);
62     solve(mid+1,R,ql+lql,qr);
63 }
64 
65 int a[maxn];
66 int main()
67 {
68     scanf("%d%d",&n,&m);
69     for (int i=1;i<=n;i++) scanf("%d",&q[i].y),a[i]=q[i].y,q[i].x=i,q[i].z=1,q[i].type=0;
70     char s[5];
71     int cntq=0;
72     for (int i=1,j=n+1;i<=m;i++,j++)
73     {
74         scanf("%s",s);
75         if (s[0]=='Q') scanf("%d%d%d",&q[j].x,&q[j].y,&q[j].z),q[j].id=++cntq,q[j].type=1;
76         else scanf("%d%d",&q[j].x,&q[j].y),q[j].z=1,q[j].type=0,
77         q[j+1]=(Ope){q[j].x,a[q[j].x],-1,0,0},a[q[j].x]=q[j].y,j++;
78         if (i==m) len=j;
79     }
80     solve(0,inf,1,len);
81     for (int i=1;i<=cntq;i++) printf("%d\n",ans[i]);
82     return 0;
83 }
View Code

 

posted @ 2018-01-07 21:24  Blue233333  阅读(...)  评论(...编辑  收藏