1. 程式人生 > >Luogu3960 NOIP2017列隊(splay)

Luogu3960 NOIP2017列隊(splay)

  令splay中的一個點表示一段區間,需要使用其中某個點時將區間分裂即可,剩下的都是splay的基本操作了。寫的非常醜陋,注意細節。感覺考場上肯定只能靠部分分苟活了。想起來去年因為各種莫名其妙的原因50->0

  線段樹做法待補。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define
N 300010 #define lson tree[k].ch[0] #define rson tree[k].ch[1] char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while
(c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,q,row[N],line,cnt; struct data{int ch[2],fa,len,size;ll id; }tree[N<<4]; ll trans(int x,int y){return 1ll*(x-1)*m+y;} void up(int
k){tree[k].size=tree[lson].size+tree[rson].size+tree[k].len;} int whichson(int k){return tree[tree[k].fa].ch[1]==k;} void move(int k) { int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k); tree[gf].ch[whichson(fa)]=k,tree[k].fa=gf; tree[tree[k].ch[!p]].fa=fa,tree[fa].ch[p]=tree[k].ch[!p]; tree[k].ch[!p]=fa,tree[fa].fa=k; up(fa),up(k); } void splay(int k,int rt,int &root) { while (tree[k].fa!=rt) { int fa=tree[k].fa; if (tree[fa].fa!=rt) if (whichson(fa)^whichson(k)) move(k); else move(fa); move(k); } if (!rt) root=k; } int find(int k,int x) { if (tree[lson].size<x&&tree[lson].size+tree[k].len>=x) return k; else if (tree[lson].size>=x) return find(lson,x); else return find(rson,x-tree[lson].size-tree[k].len); } int getid(int k,int x) { if (tree[lson].size<x&&tree[lson].size+tree[k].len>=x) return x-tree[lson].size; else if (tree[lson].size>=x) return getid(lson,x); else return getid(rson,x-tree[lson].size-tree[k].len); } int nxt(int k){if (!lson) return k;return nxt(lson);} void ins(int &k,int l,int r,ll id) { cnt++;tree[cnt].size=tree[cnt].len=r-l+1,tree[cnt].id=id; int p=find(k,l);splay(p,0,k); int q=nxt(tree[p].ch[1]);splay(q,p,k); tree[q].ch[0]=cnt;tree[cnt].fa=q;up(q);up(p); } void del(int &k,int l,int r) { int p=find(k,l),q=find(k,r+2); splay(p,0,k);splay(q,p,k); tree[q].ch[0]=0;up(q);up(p); } ll split(int x,int y) { int k=find(row[x],y+1),p=getid(row[x],y+1); del(row[x],y-p+1,y+tree[k].len-p); if (p>1) ins(row[x],y-p+1,y-1,tree[k].id); if (p<tree[k].len) ins(row[x],y,y+tree[k].len-p-1,tree[k].id+p); return tree[k].id+p-1; } int main() { #ifndef ONLINE_JUDGE freopen("phalanx.in","r",stdin); freopen("phalanx.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),q=read(); for (int i=1;i<=n;i++) { row[i]=++cnt;tree[cnt].len=m-1,tree[cnt].size=m+1;tree[cnt].id=trans(i,1); cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=row[i],tree[row[i]].ch[0]=cnt; cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=row[i],tree[row[i]].ch[1]=cnt; } line=++cnt;tree[cnt].len=1,tree[cnt].size=2; cnt++;tree[cnt].len=tree[cnt].size=1;tree[cnt].fa=line,tree[line].ch[1]=cnt; for (int i=1;i<=n;i++) ins(line,i,i,trans(i,m)); while (q--) { int x=read(),y=read(); ll id; if (y<m) { id=split(x,y); int k=find(line,x+1); del(line,x,x); ins(row[x],m-1,m-1,tree[k].id); } else { int k=find(line,x+1); del(line,x,x); id=tree[k].id; } ins(line,n,n,id); printf(LL,id); } return 0; }