[NOIP2017]列队(线段树/裂点splay)

考虑n=1的做法,就是支持:

1.在线删一个数

2.在结尾加一个数

3.查询序列的第y个数

用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可。

对于满分同样如此,对每行开一个线段树,再对最后一列单独开一个。

对于每次操作:

若在最后一列:就是对最后一列直接使用n=1的做法。

若不在:对第x列的前m-1个用n=1的做法,再将最后一列的第x个加入第x列的末尾,然后再对最后一列使用n=1的做法。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 #define lson ls[x],L,mid
 5 #define rson rs[x],mid+1,R
 6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 7 typedef long long ll;
 8 using namespace std;
 9 
10 const int N=300010,M=N*40;
11 ll ans;
12 int n,m,Q,mx,x,y,nd,rt[N],sm[M],ls[M],rs[M];
13 vector<ll>V[N];
14 
15 void ins(int &x,int L,int R,int pos){
16     if (!x) x=++nd;
17     if (L==R){ sm[x]++; return; }
18     int mid=(L+R)>>1;
19     if (pos<=mid) ins(lson,pos); else ins(rson,pos);
20     sm[x]=sm[ls[x]]+sm[rs[x]];
21 }
22 
23 int que(int x,int L,int R,int pos){
24     if (L==R) return L;
25     int mid=(L+R)>>1,t=mid-L+1-sm[ls[x]];
26     if (t>=pos) return que(lson,pos); else return que(rson,pos-t);
27 }
28 
29 int main(){
30     scanf("%d%d%d",&n,&m,&Q); mx=max(n,m)+Q;
31     rep(i,0,n) V[i].push_back(0);
32     while (Q--){
33         scanf("%d %d",&x,&y);
34         if (y==m){
35             int s=que(rt[0],1,mx,x);
36             if (s<=n) ans=1ll*s*m; else ans=V[0][s-n];
37             printf("%lld\n",ans); ins(rt[0],1,mx,s); V[0].push_back(ans);
38             continue;
39         }
40         int t=que(rt[x],1,mx,y);
41         if (t<m) ans=1ll*(x-1)*m+t; else ans=V[x][t-(m-1)];
42         printf("%lld\n",ans); ins(rt[x],1,mx,t);
43         int s=que(rt[0],1,mx,x); ll tmp=ans;
44         if (s<=n) ans=1ll*s*m; else ans=V[0][s-n];
45         V[x].push_back(ans); ins(rt[0],1,mx,s); V[0].push_back(tmp);
46     }
47     return 0;
48 }

 

或裂点splay,一个点代表一个区间,每次删除某个位置k就将其裂为[l,k-1],k,[k+1,r]三个部分,再删掉k。

模板题。常数较大。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=2000010;
 8 int n,m,Q,nd,x,y,ch[N][2],rt[N],f[N];
 9 ll L[N],R[N],len[N];
10 
11 int get(ll l,ll r){ nd++; L[nd]=l; R[nd]=r; len[nd]=r-l+1; return nd; }
12 void upd(int x){ len[x]=len[ch[x][0]]+len[ch[x][1]]+R[x]-L[x]+1; }
13 
14 void rot(int &rt,int x){
15     int y=f[x],z=f[y],w=ch[y][1]==x;
16     if (y==rt) rt=x; else ch[z][ch[z][1]==y]=x;
17     f[x]=z; f[y]=x; f[ch[x][w^1]]=y;
18     ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; upd(y);
19 }
20 
21 void splay(int &rt,int x){
22     while (x!=rt){
23         int y=f[x],z=f[y];
24         if (y!=rt) ((ch[z][0]==y) ^ (ch[y][0]==x)) ? rot(rt,x) : rot(rt,y);
25         rot(rt,x);
26     }
27     upd(x);
28 }
29 
30 void ins(int &rt,ll k){
31     int y=get(k,k);
32     if (!rt) { rt=y; return; }
33     int x=rt; while (ch[x][1]) x=ch[x][1];
34     splay(rt,x); f[y]=x; ch[x][1]=y; upd(x);
35 }
36 
37 int split(int &rt,int x,ll k){
38     k+=L[x];
39     int y=get(k,R[x]); R[x]=k-1;
40     if (!ch[x][1]) f[y]=x,ch[x][1]=y;
41     else{
42         int s=ch[x][1];
43         while (ch[s][0]) s=ch[s][0];
44         f[y]=s; ch[s][0]=y;
45     }
46     splay(rt,y); return y;
47 }
48 
49 int find(int x,ll &k){
50     if (k<=len[ch[x][0]]) return find(ch[x][0],k);
51     k-=len[ch[x][0]];
52     if (k<=R[x]-L[x]+1) return x; else return k-=R[x]-L[x]+1,find(ch[x][1],k);
53 }
54 
55 ll del(int &rt,ll k){
56     int x=find(rt,k);
57     if (k<R[x]-L[x]+1) split(rt,x,k);
58     if (k>1) x=split(rt,x,k-1);
59     splay(rt,x); f[ch[x][0]]=f[ch[x][1]]=0;
60     if (!ch[x][0]) rt=ch[x][1];
61     else{
62         int y=ch[x][0]; rt=y;
63         while (ch[y][1]) y=ch[y][1];
64         splay(rt,y); ch[y][1]=ch[x][1];
65         f[ch[x][1]]=y; upd(y);
66     }
67     return L[x];
68 }
69 
70 int main(){
71     freopen("phalanx.in","r",stdin);
72     freopen("phalanx.out","w",stdout);
73     scanf("%d%d%d",&n,&m,&Q);
74     rep(i,1,n) rt[i]=++nd,L[i]=(i-1ll)*m+1,R[i]=1ll*i*m-1,len[i]=R[i]-L[i]+1;
75     rep(i,1,n) ins(rt[0],1ll*i*m);
76     while (Q--){
77         scanf("%d%d",&x,&y); ll ans;
78         ins(rt[x],del(rt[0],x));
79         printf("%lld\n",ans=del(rt[x],y));
80         ins(rt[0],ans);
81     }
82     return 0;
83 }

 

posted @ 2018-11-03 20:23  HocRiser  阅读(246)  评论(0编辑  收藏  举报