很水的一道Splay维护题
好吧我其实被卡的很惨。。。
常数大的要死
注意一下放标的顺序与时机这样可以大大减小常数
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> using namespace std; char c; #define ll long long inline void read(ll &a) { a=0;do c=getchar();while(c<'0'||c>'9'); while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar(); } const ll mod=20130426; struct Node { Node *lc,*rc,*f; ll DeBug; ll add_delta,k_delta; ll ax_delta; ll k,ax; inline bool l(){return f->lc==this;} inline bool flag(){return add_delta||k_delta!=1||ax_delta;} inline friend Node operator +=(Node &a,Node b) { a.k+=b.k; return a; } }Tree[100002]; Node *root,*empty; Node *build(ll l,ll r) { if(r<l)return empty; Node *tp=&Tree[(l+r)>>1]; tp->lc=build(l,((l+r)>>1)-1),tp->lc->f=tp, tp->rc=build(((l+r)>>1)+1,r),tp->rc->f=tp; return tp; } inline void begin() { empty=new Node; empty->lc=empty; empty->rc=empty; for(ll i=0;i<=100001;i++) Tree[i].ax=Tree[i].DeBug=i,Tree[i].k=0,Tree[i].add_delta=Tree[i].ax_delta=0,Tree[i].k_delta=1; root=build(0,100001); root->f=root; Tree[100001].ax=1ll<<62; } int ttp; inline void Mod(Node *a) { if(a==empty)return; ttp+=3; a->k%=mod;a->add_delta%=mod;a->k_delta%=mod; } void pushdown(Node *a) { a->lc->add_delta=a->lc->add_delta*a->k_delta+a->add_delta; a->rc->add_delta=a->rc->add_delta*a->k_delta+a->add_delta; a->lc->k_delta=a->lc->k_delta*a->k_delta; a->rc->k_delta=a->rc->k_delta*a->k_delta; a->k=a->k*a->k_delta+a->add_delta; a->lc->ax_delta+=a->ax_delta; a->rc->ax_delta+=a->ax_delta; a->ax+=a->ax_delta; a->ax_delta=0; a->k_delta=1; a->add_delta=0; Mod(a->lc),Mod(a->rc),Mod(a); } inline void Lc(Node *a) { Node *f; if(a->f==root) f=a,root=a; else if(a->f->l()) a->f->f->lc=a,f=a->f->f; else a->f->f->rc=a,f=a->f->f; a->rc->f=a->f; a->f->lc=a->rc; a->f->f=a; a->rc=a->f; a->f=f; } inline void Rc(Node *a) { Node *f; if(a->f==root) f=a,root=a; else if(a->f->l()) a->f->f->lc=a,f=a->f->f; else a->f->f->rc=a,f=a->f->f; a->lc->f=a->f; a->f->rc=a->lc; a->f->f=a; a->lc=a->f; a->f=f; } inline void Change(Node *a) {a->l()?Lc(a):Rc(a);} inline void TwiChange(Node *a) {a->l()==a->f->l()?Change(a->f):Change(a);Change(a);} inline void Rotato(Node *a) { while(a->f!=root)TwiChange(a); if(a!=root)Change(a); } inline void Rotato2(Node *a) { while(a->f->f!=root)TwiChange(a); if(a->f!=root)Change(a); } Node* FindPre(ll ax,Node *tp) { Node *res; if(tp==empty)return tp; if(tp->flag())pushdown(tp); if(tp->ax>=ax)return (res=FindPre(ax,tp->lc))==empty?empty:res; return (res=FindPre(ax,tp->rc))==empty?tp:res; } Node* FindAft(ll ax,Node *tp) { Node *res; if(tp==empty)return tp; if(tp->flag())pushdown(tp); if(tp->ax>ax)return (res=FindAft(ax,tp->lc))==empty?tp:res; return (res=FindAft(ax,tp->rc))==empty?empty:res; } inline Node* Div(ll l,ll r) { Node *L; if((L=FindPre(l,root))!=empty) { Rotato(L),Rotato2(FindAft(r,root)); return root->rc->lc; } else { Rotato(FindAft(r,root)); return root->lc; } } inline void Oper1() { ll v,l,r; read(l),read(r),read(v); Node *R=Div(l,r); R->k_delta*=v; R->add_delta*=v; Mod(R); } inline void Oper2() { ll v,l,r; read(l),read(r),read(v); Div(l,r)->add_delta+=v; } void Insert(Node *Cache,Node *tp) { if(tp->flag())pushdown(tp); if(Cache->ax<tp->ax) if(tp->lc==empty) Cache->f=tp,tp->lc=Cache; else Insert(Cache,tp->lc); else if(tp->rc==empty) Cache->f=tp,tp->rc=Cache; else Insert(Cache,tp->rc); } inline void Oper3() { ll l,r; read(l),read(r); Div(l,r)->ax_delta++; Node *tp=FindAft(r,root); Node *tp2=FindPre(r+2,root); tp2->k+=tp->k; while(tp->lc!=empty||tp->rc!=empty) tp->lc!=empty?Change(tp->lc):Change(tp->rc); (tp->l()?tp->f->lc:tp->f->rc)=empty; tp->ax=l; tp->k=0; tp->k_delta=1; tp->add_delta=0; tp->ax_delta=0; Insert(tp,root); } ll Query(ll a,ll &tmp,Node *tp) { if(tp==empty)return 0; if(tp->flag())pushdown(tp); ll res=Query(a,tmp,tp->lc); res+=tp->k*1ll*tmp; tmp=(a*1ll*tmp)%mod; return res=(res+Query(a,tmp,tp->rc))%mod; } inline void Oper4() { ll v,tp=1; read(v); Rotato(&Tree[100001]); printf("%lld\n",Query(v,tp,root->lc)); } ll n; int main() { begin(); read(n); while(n--) { do c=getchar();while(c!='a'&&c!='q'&&c!='m'); if(c=='a') Oper2(); else if(c=='m') { c=getchar();c=getchar();c=getchar(); if(c=='x')Oper3(); else Oper1(); } else Oper4(); } return 0; }