[BZOJ]1895: Pku3580 supermemo
题解:splay裸题 直接扒了以前poj的代码...ac+1
#include <iostream> #include <algorithm> #include <cstdio> #define N 400005 #define rl ch[ch[root][1]][0] #define lr ch[ch[root][0]][1] #define INF 0x3f3f3f3f #define ll long long using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int size[N],pre[N],ch[N][2]; ll add[N],flag[N],key[N],Min[N]; int a[N],s[N]; int root,cnt1,cnt2,n; void newnode(int &x,int fa,int vul){ if(cnt2) x=s[cnt2--]; else x=(++cnt1); size[x]=1;pre[x]=fa;Min[x]=key[x]=vul; ch[x][0]=ch[x][1]=add[x]=flag[x]=0; } void reverse(int x){ if(!x) return ; swap(ch[x][0],ch[x][1]); flag[x]^=1; } void push(int x){ if(add[x]){ if(ch[x][0]) { add[ch[x][0]]+=add[x];Min[ch[x][0]]+=add[x];key[ch[x][0]]+=add[x];} if(ch[x][1]) { add[ch[x][1]]+=add[x];Min[ch[x][1]]+=add[x];key[ch[x][1]]+=add[x];} add[x]=0; } if(flag[x]){ if(ch[x][0]) reverse(ch[x][0]); if(ch[x][1]) reverse(ch[x][1]); flag[x]=0; } } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+1; Min[x]=min(key[x],min(Min[ch[x][0]],Min[ch[x][1]])); } void rotate(int x,int kind){ int y=pre[x]; push(y);push(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];pre[y]=x;ch[x][kind]=y; up(y);up(x); } void splay(int x,int goal){ push(x); while(pre[x]!=goal){ if(pre[pre[x]]==goal){ push(pre[x]);push(x); int kind=ch[pre[x]][0]==x; rotate(x,kind); } else{ int y=pre[x]; push(pre[y]);push(y);push(x); int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind);rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } if(goal==0) root=x; up(x); } int find1(int x,int t){ push(x); if(t==size[ch[x][0]]+1) return x; else if(t<size[ch[x][0]]+1) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); up(x); } void Add(int l,int r,int vul){ splay(find1(root,l),0);splay(find1(root,r+2),root); add[rl]+=vul;Min[rl]+=vul;key[rl]+=vul; up(ch[root][1]);up(root); } void update(int l,int r){ splay(find1(root,l),0);splay(find1(root,r+2),root); reverse(rl); up(ch[root][1]);up(root); } void revolve(int l,int r,int t){ int len=t%(r-l+1); if(!len) return ; splay(find1(root,r-len+1),0); splay(find1(root,r+2),root); up(ch[root][1]);up(root); int tmp=rl; rl=0; splay(find1(root,l),0); splay(find1(root,l+1),root); pre[tmp]=ch[root][1]; rl=tmp; up(ch[root][1]); up(root); } void insert(int t,int p){ splay(find1(root,t+1),0); splay(find1(root,t+2),root); newnode(rl,ch[root][1],p); up(ch[root][1]);up(root); } void delet(int t){ splay(find1(root,t),0); splay(find1(root,t+2),root); s[++cnt2]=rl; pre[rl]=0; rl=0; up(ch[root][1]);up(root); } int min1(int l,int r){ splay(find1(root,l),0); splay(find1(root,r+2),root); return Min[rl]; } void built(int &x,int l,int r,int fa){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,fa,a[mid]); built(ch[x][0],l,mid-1,x); built(ch[x][1],mid+1,r,x); up(x); } void init(){ for(int i=1;i<=n;i++) a[i]=read(); root=cnt1=cnt2=0; size[root]=pre[root]=add[root]=flag[root]=ch[root][0]=ch[root][1]=0; Min[root]=INF; newnode(root,0,INF); newnode(ch[root][1],root,INF); built(rl,1,n,ch[root][1]); up(ch[root][1]);up(root); } int main(){ n=read(); init(); int q=read();char str[102]; int t1,t2,t3; while(q--){ scanf("%s",str); if(str[0]=='A'){ t1=read();t2=read();t3=read(); Add(t1,t2,t3); } else if(str[0]=='R'&&str[3]=='E'){ t1=read();t2=read(); update(t1,t2); } else if(str[0]=='R'){ t1=read();t2=read();t3=read(); revolve(t1,t2,t3); } else if(str[0]=='I'){ t1=read();t2=read(); insert(t1,t2); } else if(str[0]=='D'){ t1=read(); delet(t1); } else if(str[0]=='M'){ t1=read();t2=read(); printf("%d\n",min1(t1,t2)); } } return 0; }
1895: Pku3580 supermemo
Time Limit: 15 Sec Memory Limit: 64 MBSubmit: 643 Solved: 245
[Submit][Status][Discuss]
Description
给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执 行"REVERSE 24"会得到f1,4,3,2,5g。 3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如, 对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得 到f1,3,4,5g。 6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。
Input
第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。
Output
对于所有"MIN"操作,输出正确的答案,每行一个。
Sample Input
5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
Sample Output
5
HINT
输入、输出以及中间运算结果均不会超过32位整数。
对于30%的数据,n;m 6 1000;
对于100%的数据,n;m 6 100000。