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 }

 

posted @ 2020-08-19 15:06  ZMWLxh  阅读(527)  评论(0编辑  收藏  举报