码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3580 SuperMemo 题解

时间:2015-03-10 22:56:49      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:维护一个序列,支持6种操作:

1、ADD x y D 从第x个数到第y个数都增加D

2、REVERSE x y 翻转第x个数到第y个数

3、REVOLVE x y T 从x到y,向右循环移动T次

4、INSERT x P 插入P到第x个数后面

5、DELETE x 删除第x个数

6、MIN x y 查询第x个数到第y个数之间最小值

ADD和REVERSE打标记然后及时下传就可以。。REVOLVE的T可能为负还可能很大,要注意取模。REVOLVE可以通过3个REVERSE操作完成,也可以通过分离和合并完成,只不过代码稍微长一点。INSERT可以将x提到根,x+1提到root下面,此时根节点的右儿子的左儿子为空,新建一个结点,维护信息。也可以将x提到根,新建结点t,使t->ch[1]=root->ch[1],再使root->ch[1]=t。DELETE可以将x-1提到根,x+1提到root下面,删除root->ch[1]->ch[0],维护信息。 

代码长,细节多。。容易出错。这题好像RE会显示TLE。。不知道是什么问题

技术分享
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 const int INF=~0U>>1;
  5 const int MAXN=100000+10;
  6 int n,m;
  7 int a[MAXN];
  8 struct Node{
  9     int s,v,add,mn;
 10     bool rev;
 11     Node* p,*ch[2];
 12     Node() {s=0;add=0;v=mn=INF;}
 13     inline bool d() {return p->ch[1]==this;}
 14     inline void setc(Node* o,int d)
 15     {
 16         ch[d]=o;
 17         o->p=this;
 18     }
 19     inline void addIt(int x)
 20     {
 21         add+=x;
 22         mn+=x;
 23         v+=x;
 24     }
 25     inline void revIt()
 26     {
 27         rev^=1;
 28     }
 29     inline void maintain()
 30     {
 31         s=ch[0]->s+ch[1]->s+1;
 32         mn=std::min(v,std::min(ch[0]->mn,ch[1]->mn));
 33     }
 34     inline void pushdown();
 35 }Tnull,*null=&Tnull;
 36 Node mem[MAXN<<1],*C=mem;
 37 inline void Node::pushdown()
 38 {
 39     if(add)
 40     {
 41         if(ch[0]!=null) ch[0]->addIt(add);
 42         if(ch[1]!=null) ch[1]->addIt(add);
 43         add=0;
 44     }
 45     if(rev)
 46     {
 47         std::swap(ch[0],ch[1]);
 48         if(ch[0]!=null) ch[0]->revIt();
 49         if(ch[1]!=null) ch[1]->revIt();
 50         rev=0;
 51     }
 52 }
 53 inline Node* newnode(int v)
 54 {
 55     C->ch[0]=C->ch[1]=null;
 56     C->s=1;
 57     C->v=C->mn=v;
 58     C->add=C->rev=0;
 59     return C++;
 60 }
 61 Node* build(int l,int r) //[l,r)
 62 {
 63     if(l>=r) return null;
 64     int m=l+(r-l)/2;
 65     Node* t=newnode(a[m]);
 66     t->setc(build(l,m),0);
 67     t->setc(build(m+1,r),1);
 68     t->maintain();
 69     return t;
 70 }
 71 Node* root;
 72 inline void rot(Node* t)
 73 {
 74     Node* p=t->p;
 75     p->pushdown();t->pushdown();
 76     int d=t->d();
 77     p->p->setc(t,p->d());
 78     p->setc(t->ch[d^1],d);
 79     t->setc(p,d^1);
 80     p->maintain();
 81     if(p==root)
 82         root=t;
 83 }
 84 void splay(Node* t,Node* f=null)
 85 {
 86     while(t->p!=f)
 87     {
 88         if(t->p->p==f) rot(t);
 89         else t->d()==t->p->d()?(rot(t->p),rot(t)):(rot(t),rot(t));
 90     }
 91     t->maintain();
 92 }
 93 Node* select(int k,Node* t=root)
 94 {
 95     for(Node* t=root;;)
 96     {
 97         t->pushdown();
 98         int s=t->ch[0]->s;
 99         if(k==s) return t;
100         if(k>s) k-=s+1,t=t->ch[1];
101         else t=t->ch[0];
102     }
103 }
104 inline Node*& get(int l,int r) //[l,r)
105 {
106     Node* L=select(l-1);
107     Node* R=select(r);
108     splay(L);
109     splay(R,root);
110     return R->ch[0];
111 }
112 inline void Reverse(int l,int r)
113 {
114     Node*& t=get(l,r+1);
115     t->revIt();
116 }
117 inline void Insert(int x,int P)
118 {
119     splay(select(x));
120     Node* t=newnode(P);
121     t->setc(root->ch[1],1);
122     root->setc(t,1);
123     t->maintain();
124     root->maintain();
125 }
126 inline void Add(int x,int y,int D)
127 {
128     Node*& t=get(x,y+1);
129     t->addIt(D);
130 }
131 inline void Revolve(int x,int y,int T)
132 {
133     int l=y+1-x;
134     T=(T%l+l)%l;
135     if(T==0) return;
136     Reverse(x,y);
137     Reverse(x,x+T-1);
138     Reverse(x+T,y);
139 }
140 inline int Min(int x,int y)
141 {
142     Node* &t=get(x,y+1);
143     return  t->mn;
144 }
145 inline void Delete(int x)
146 {
147     splay(select(x-1));
148     splay(select(x+1),root);
149     root->ch[1]->ch[0]=null;
150     root->ch[1]->maintain();
151     root->maintain();
152 }
153 int main()
154 {
155 //    freopen("1.in","r",stdin);
156     scanf("%d",&n);
157     for(int i=1;i<=n;++i)
158         scanf("%d",a+i);
159     a[0]=a[n+1]=INF;
160     root=build(0,n+2);
161     root->p=null;
162     scanf("%d",&m);
163     while(m--)
164     {
165         int x,y,k;
166         char s[20];
167         scanf("%s",s);
168         switch(s[0])
169         {
170             case A:scanf("%d%d%d",&x,&y,&k);
171                      Add(x,y,k);
172                      break;
173             case I:scanf("%d%d",&x,&k);
174                      Insert(x,k);
175                      break;
176             case D:scanf("%d",&x);
177                      Delete(x);
178                      break;
179             case M:scanf("%d%d",&x,&y);
180                      printf("%d\n",Min(x,y));
181                      break;
182             case R:if(s[3]==E)
183                      {
184                          scanf("%d%d",&x,&y);
185                         Reverse(x,y);
186                      }
187                      else
188                      {
189                          scanf("%d%d%d",&x,&y,&k);
190                         Revolve(x,y,k);
191                      }
192         }
193     }
194     return 0;
195 }
View Code

 

POJ 3580 SuperMemo 题解

标签:

原文地址:http://www.cnblogs.com/lowsfish/p/4328596.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!