HDU多校2020 第九场 G-Game(fhq treap+维护区间移动
题意:http://acm.hdu.edu.cn/showproblem.php?pid=6873
推格子,和牛客多校2020某场操作几乎原模原样,只是询问更加细节
思路:
fhq treap,之前没学,学了之后就是那个min操作相关的split有点小妙其他一般般吧
1 #define int ll 2 int a[N]; 3 4 class TREAP 5 { 6 public: 7 int tot; 8 int tr[N][2],sz[N],val[N],rnd[N],min_[N],sum[N]; 9 void Init() 10 { 11 tot=0; 12 min_[0]=inf; 13 } 14 int newnode(int x){ 15 ++tot; 16 sz[tot]=1; 17 sum[tot]=min_[tot]=val[tot]=x; 18 tr[tot][0]=tr[tot][1]=0; 19 rnd[tot]=rand_num()%mod; 20 return tot; 21 } 22 void up(int rt){ 23 sz[rt]=1+sz[tr[rt][0]]+sz[tr[rt][1]]; 24 sum[rt]=val[rt]+sum[tr[rt][0]]+sum[tr[rt][1]]; 25 min_[rt]=min(val[rt],min(min_[tr[rt][0]],min_[tr[rt][1]])); 26 } 27 void split_by_sz(int now,int leftsz,int &x,int &y){ 28 if(!now){x=y=0;return;} 29 if(leftsz<=sz[tr[now][0]])y=now,split_by_sz(tr[now][0],leftsz,x,tr[now][0]); 30 else x=now,split_by_sz(tr[now][1],leftsz-sz[tr[now][0]]-1,tr[now][1],y); 31 up(now); 32 } 33 void split_by_v(int now,int v,int &x,int &y){ 34 if(!now){x=y=0;return;} 35 if(!(val[now]>=v&&min_[tr[now][1]]>=v))x=now,split_by_v(tr[now][1],v,tr[now][1],y); 36 else y=now,split_by_v(tr[now][0],v,x,tr[now][0]); 37 up(now); 38 } 39 int merge(int x,int y){//注意这个操作的返回值是根节点 40 if(!x||!y)return x+y;//如果有一棵树是空的,返回另一棵树就可以 41 if(rnd[x]<rnd[y]){//比较修正值 42 tr[x][1]=merge(tr[x][1],y);//把y合并到x的右子树 43 up(x); 44 return x; 45 } 46 else{ 47 tr[y][0]=merge(x,tr[y][0]);//把x合并到y的左子树 48 up(y); 49 return y; 50 } 51 } 52 void insert(int pos,int v,int &rt){ 53 int x,y; 54 split_by_sz(rt, pos-1, x, y); 55 rt = merge(merge(x ,newnode(v)), y); 56 } 57 int kth(int now,int k){ 58 if(k>sz[tr[now][0]]&&k<=sz[now]-sz[tr[now][1]])return val[now]; 59 if(k<=sz[tr[now][0]])return kth(tr[now][0],k); 60 else return kth(tr[now][1],k-(sz[now]-sz[tr[now][1]])); 61 } 62 //===========================题目函数 63 ll Lmove(int x,int y,int &rt) 64 { 65 if(kth(rt,x)<y) return 0LL; 66 int lls,rrs; 67 int z,zz,x1,x2,x3,x4; 68 split_by_sz(rt,x,lls,rrs); 69 if(min_[lls]>=y)return rt=merge(lls,rrs),0LL; 70 split_by_v(lls,y,z,zz); 71 ll res=sum[zz]-1LL*(y-1)*sz[zz]; 72 split_by_sz(zz,1,x1,x2); 73 int tmp=val[x1]-y+1,cnt=sz[z],cntx2=sz[x2]; 74 split_by_sz(z,cnt-1,x3,x4); 75 int v4=val[x4]+tmp; 76 rt=merge(merge(x3,x2),rrs); 77 insert(cnt,v4,rt),insert(x,y-1,rt); 78 return res; 79 } 80 }treap; 81 82 void solve() 83 { 84 int n,m; 85 FI(n),FI(m); 86 treap.Init(); 87 int rt=0; 88 for(int i=1;i<=n;++i) 89 { 90 FI(a[i]); 91 treap.insert(i,a[i],rt); 92 } 93 for(int i=1;i<=m;++i) 94 { 95 int op,x,y; 96 FI(op); 97 if(op==1) 98 { 99 FI(x),FI(y); 100 FO(treap.Lmove(x,y,rt)); 101 FO('\n'); 102 } 103 else 104 { 105 FI(x); 106 FO(treap.kth(rt,x)); 107 FO('\n'); 108 } 109 } 110 for(int i=1;i<=n;++i) 111 { 112 FO(treap.kth(rt,i)); 113 if(i==n)FO('\n'); 114 else FO(' '); 115 } 116 Flush; 117 } 118 119 signed main() 120 { 121 int T; 122 sc("%lld",&T); 123 while(T--)solve(); 124 return 0; 125 }