BZOJ 3323 多项式的运算 发表于 2017-03-14 | 更新于 2018-06-18 Link一开始被题意唬了一下。。 Solution对mulx操作,在左边插入一个0,删掉右端点并把系数加到右端点右边的端点 注意含有0,所以需要加加减减,然而Splay内部的空节点也要加加减减,所以要小心 Code123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215#include "lucida"const int MAXN=1e5+11,P=20130426;struct Line { int64 k,b; Line():k(1),b(0){} Line(int64 k,int64 b):k(k),b(b){} operator bool() { return !(k==1 && b==0); } int64 operator () (int64 x) { return (k*x+b)%P; } Line operator () (Line x) { return Line(k*x.k%P,(k*x.b+b)%P); }};namespace splay { struct Node *null; struct Node { Node *son[2],*fa; int64 v;int sz;Line mrk; Node():v(v),sz(0) { son[0]=son[1]=fa=null; } Node(int64 v):v(v),sz(1) { son[0]=son[1]=fa=null; } void *operator new(size_t) { static Node *Me=alloc(Node,MAXN<<2); return Me++; } bool isRoot() { return fa==null; } int Kind() { return fa->son[1]==this; } void Modify(Line ln) { if(this==null) return; v=ln(v); mrk=ln(mrk); } void Up() { sz=son[0]->sz+son[1]->sz+1; } void Down() { if(mrk) { son[0]->Modify(mrk); son[1]->Modify(mrk); mrk.k=1;mrk.b=0; } } }*llun=null=new Node; struct Splay { Node *root; Splay(){ (root=new Node(0))->son[1]=new Node(0); (root->son[1]->fa=root)->Up(); } void Trans(Node *pos) { Node *f=pos->fa,*grf=f->fa; f->Down();pos->Down();//反过来写会导致一些标记下传2次 int d=pos->Kind(); if(!f->isRoot()) grf->son[f->Kind()]=pos; pos->fa=grf;//没写?? f->son[d]=pos->son[!d];pos->son[!d]->fa=f; pos->son[!d]=f;f->fa=pos; f->Up(); } void SplayTo(Node *pos,Node *goal) { Node *f; while((f=pos->fa)!=goal) { if(f->fa!=goal) Trans(f->Kind()==pos->Kind()?f:pos); Trans(pos); } pos->Up(); if(goal==null) root=pos; } Node *Kth(int K) { ++K; Node *pos=root;int c; while(pos!=null) { if((c=pos->son[0]->sz+1)==K) break; else if(K<c) pos=pos->son[0]; else { pos=pos->son[1]; K-=c; } } SplayTo(pos,null); return pos; } Node *Split(int L,int R) { Node *p1=Kth(L-1),*p2=Kth(R+1); SplayTo(p1,null); SplayTo(p2,p1); return p2->son[0]; } void Insert(int pos,Node *newn) { Node *p1=Kth(pos),*p2=Kth(pos+1); SplayTo(p1,null); SplayTo(p2,p1); p1->Down(),p2->Down(); p2->son[0]=newn;newn->fa=p2; SplayTo(newn,null); } Node* Insert(int pos,int v) { Node *newn=new Node(v); Insert(pos,newn); return newn; } void Delete(int pos) { Node *rt=Split(pos,pos); rt->fa->son[0]=null;//rt->son[0]=null... SplayTo(rt->fa,null); } Node *Build(int L,int R) { int Mid=(L+R)>>1; Node *pos=new Node(0); if(L!=Mid) (pos->son[0]=Build(L,Mid-1))->fa=pos; if(Mid!=R) (pos->son[1]=Build(Mid+1,R))->fa=pos; pos->Up(); return pos; } void Make(int size) { int sz=root->sz-2; if((size-=sz)>0) Insert(sz,Build(1,size)); } //对外的interface L,R是包含0的 void Modify(int L,int R,Line ln) { ++L,++R; Make(R); Node *rt=Split(L,R); rt->Modify(ln); SplayTo(rt,null); } int64* Out(Node *pos,int &cnt) { static int64 seq[MAXN]; if(pos!=null) { pos->Down(); Out(pos->son[0],cnt); seq[++cnt]=pos->v; Out(pos->son[1],cnt); } return seq; } void Print() { int cnt=0; int64 *s=Out(root,cnt); for(int i=1;i<=cnt;++i) os<<s[i]<<' '; os<<'\n'; } int Query(int v) { v%=P; int cnt=0; int64 *s=Out(root,cnt); int64 powx=1,res=0; for(int i=2;i<=cnt-1;++i) { (res+=powx*s[i])%=P; (powx*=v)%=P; } return res; } void Mulx(int L,int R) { ++L,++R; Make(R+1); int rv=Kth(R)->v; Delete(R); Insert(L-1,0); Modify(R,R,Line(1,rv));//Modify是对外部的interface 会自行++ } };}using splay::Splay;int main() { freopen("input","r",stdin); int n;is>>n; Splay sp; for(int i=1;i<=n;++i) { char opt[10];int L,R,v,Ans; is>>opt; switch(opt[0]) { case 'm': if(opt[3]=='x') { is>>L>>R; sp.Mulx(L,R); } else { is>>L>>R>>v; sp.Modify(L,R,Line(v,0)); } break; case 'a': is>>L>>R>>v; sp.Modify(L,R,Line(1,v)); break; case 'q': is>>v; Ans=sp.Query(v); os<<Ans<<'\n'; break; } } return 0;}