POJ3580 SuperMemo splay伸展樹,區間操作
阿新 • • 發佈:2019-01-04
題意:實現一種資料結構,支援對一個數列的 6 種操作:
第 x 個數到第 y 個數之間的數每個加 D;
第 x 個數到第 y 個數之間全部數翻轉;
第 x 個數到第 y 個數之間的數,向後迴圈流動 c 次,即後面 c個數變成這段子序列的最前面 c 個,前面的被擠到後面。
在第 x 個數後面插入一個數 P。
刪除第 x 個數。
求第 x 個數到第 y 個數之間的最小數字。
題解:
(待補)
程式碼先放上:
(是真的長啊,我已經是比較壓行的選手了,依然寫了230行)
#include <cstdio> #include <stack> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e6+10,maxm=2e6+10; const int INF=0x3f3f3f3f; typedef struct splaynode* nodep; struct splaynode{ nodep son[2],pre; ll val,tag,mn; int size,rev; void init(ll x){ pre=son[1]=son[0]=NULL; mn=val=x; tag=rev=0; size=1; } void add(ll x){tag+=x,mn+=x;} }; struct splaytree{ int cnt; stack<nodep> stk; nodep root; splaynode node[maxn+7]; int getsize(nodep x){return x?x->size:0;} void pushdown(nodep now){ if(!now) return ; if(now->tag){ ll tag=now->tag; now->val+=tag; if(now->son[0]) now->son[0]->add(tag); if(now->son[1]) now->son[1]->add(tag); now->tag=0; } if(now->rev){ swap(now->son[0],now->son[1]); now->rev=0; if(now->son[0]) now->son[0]->rev^=1; if(now->son[1]) now->son[1]->rev^=1; } } void pushup(nodep now){ if(!now) return ; now->size=1,now->mn=now->val; if(now->son[0]) { now->mn=min(now->mn,now->son[0]->mn); now->size+=now->son[0]->size; } if(now->son[1]){ now->mn=min(now->mn,now->son[1]->mn); now->size+=now->son[1]->size; } } void rotate(nodep now,int d){ nodep fa=now->pre; pushdown(fa); pushdown(now); pushdown(now->son[d]); fa->son[!d]=now->son[d]; if(now->son[d]) now->son[d]->pre=fa; now->pre=fa->pre; if(fa->pre){ if(fa->pre->son[0]==fa) fa->pre->son[0]=now; else fa->pre->son[1]=now; }else root=now; now->son[d]=fa; fa->pre=now; pushup(fa); } void splay(nodep now,nodep dst){ pushdown(now); while(now!=dst){ if(now->pre==dst){ if(dst->son[0]==now) rotate(now,1); else rotate(now,0); break; } nodep fa=now->pre,gfa=fa->pre; if(gfa->son[0]==fa){ if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);} else {rotate(now,0);rotate(now,1);} }else { if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);} else {rotate(now,1);rotate(now,0);} } if(gfa==dst) break; pushup(now); } pushup(now); } void find(int k,nodep fa){ int tmp; nodep t=root; while (1) { pushdown(t); tmp=getsize(t->son[0]); if (k==tmp+1) break; if (k<=tmp) t=t->son[0]; else { k-=tmp+1,t=t->son[1]; } } pushdown(t); splay(t, fa); } void findseg(int s,int t){ find(s,root); find(t+2,root->son[1]); } void insert(int pos,ll val){ findseg(pos+1,pos); nodep now,fa=root->son[1]; pushdown(root); pushdown(fa); if(!stk.empty()){ now=stk.top(); stk.pop(); }else now=&node[cnt++]; now->init(val); now->son[1]=fa; fa->pre=now; root->son[1]=now; now->pre=root; splay(fa,root); } void add(int s,int t,ll val){ findseg(s,t); nodep now = root->son[1]->son[0]; pushdown(now); pushup(now); now->mn+=val; now->tag+=val; splay(now,root); } void reverse(int s,int t){ findseg(s,t); root->son[1]->son[0]->rev^=1; nodep now=root->son[1]->son[0]; splay(now,root); } void revolve(int s,int t,int len){ nodep x,y; findseg(s,t); find(t+1-len,root->son[1]->son[0]); x=root->son[1]->son[0]; pushdown(x); y=x->son[1]; x->son[1]=NULL; find(s+1,root->son[1]->son[0]); x=root->son[1]->son[0]; pushdown(x); x->son[0]=y; y->pre=x; splay(y,root); } ll getmin(int s,int t) { findseg(s,t); nodep now=root->son[1]; pushdown(now); now=now->son[0]; pushdown(now); pushup(now); return now->mn; } void erase(int pos){ findseg(pos, pos); pushdown(root->son[1]); stk.push(root->son[1]->son[0]); root->son[1]->son[0] = NULL; nodep now = root->son[1]; splay(now,root); } void init(ll *a,int n){ cnt=0; root=&node[cnt++]; root->init(INF); root->son[1]=&node[cnt++]; root->son[1]->init(INF); while (!stk.empty()) stk.pop(); rep(i,0,n-1) insert(i, a[i]); } }tree; ll v[maxn]; int main() { int n, m; scanf("%d", &n); rep(i,0,n-1) scanf("%lld",&v[i]); tree.init(v, n); scanf("%d", &m); while (m--) { char s[50]; scanf("%s",s); if (s[0]=='A') { int l, r, d; scanf("%d%d%d",&l,&r,&d); tree.add(l,r,d); } if (s[0]=='R') { int l, r; scanf("%d%d",&l,&r); if (s[3]=='E') tree.reverse(l,r); else { int k; scanf("%d",&k); int tn=r-l+1; k=(k%tn+tn)%tn; if (l==r||k==0) continue; tree.revolve(l,r,k); } } if (s[0]=='I') { int x, d; scanf("%d%d",&x,&d); tree.insert(x,d); } if (s[0]=='D') { int x; scanf("%d",&x); tree.erase(x); } if (s[0]=='M') { int l, r; scanf("%d%d",&l,&r); printf("%lld\n",tree.getmin(l,r)); } } return 0; }