bzoj 1895||poj3580
2015-05-25 12:33
239 查看
对于移位操作,其实就是将[y-t+1–y]区间移动到[x,y-t+1)区间前面
具体操作:
首先取出[x,y] 区间,然后再在选取的区间内取出[y-t+1,y],然后将区间移动到最左边即可,维护过程中记得push_down(),但是别维护过头了~~
具体操作:
首先取出[x,y] 区间,然后再在选取的区间内取出[y-t+1,y],然后将区间移动到最左边即可,维护过程中记得push_down(),但是别维护过头了~~
#include <map> #include <set> #include <queue> #include <stack> #include <math.h> #include <vector> #include <cstdio> #include <string> #include<string.h> #include <fstream> #include <iostream> #include <algorithm> using namespace std; #define exp 1e-8 #define INF 0x3f3f3f3f #define ll long long #define set(a,b) memset(a,b,sizeof(a)); #define set(a,b) memset(a,b,sizeof(a)); #define for1(a,b) for(int a=1;a<=b;a++)//1---(b) #define for0(a,b) for(int a=0;a<=b;a++)//0---(b) void bug(string st="bug") {cout<<st<<endl;} template<typename __ll> inline void READ(__ll &m){ __ll x=0,f=1;char ch=getchar(); while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m=x*f; } template<typename __ll> inline void read(__ll &m){READ(m);} template<typename __ll> inline void read(__ll &m,__ll &a){READ(m);READ(a);} template<typename __ll> inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);} const int MAXN=100000*3; #define dat int #define Key_value ch[ch[root][1]][0] struct splaytree { int ch[MAXN][2]; //孩子 int pre[MAXN]; //父亲 int rev[MAXN]; //标志 dat key[MAXN]; //键值 int size[MAXN]; //大小 int add[MAXN]; int minn[MAXN]; int root,tot1; //根 结点大小 int s[MAXN],tot2; //删除用的数组,记录删除了那些点,重复利用删除的点 void addnode(int &r,int father,dat k) { if(tot2) r=s[tot2--]; else r=++tot1; ch[r][0]=ch[r][1]=rev[r]=0; pre[r]=father; key[r]=k; size[r]=1; add[r]=0; minn[r]=k; } void push_up(int r) { int lson=ch[r][0],rson=ch[r][1]; size[r]=1+size[lson]+size[rson]; minn[r]=min(key[r],min(minn[lson],minn[rson])); } void update_rev(int r) { if(!r) return ; swap(ch[r][0],ch[r][1]); rev[r]^=1; //翻来翻去 } void update_add(int r,int c) { if(!r) return ; key[r]+=c; minn[r]+=c; add[r]+=c; } void push_down(int r) { if(add[r]) { update_add(ch[r][0],add[r]); update_add(ch[r][1],add[r]); add[r]=0; } if(rev[r]) { update_rev(ch[r][0]); update_rev(ch[r][1]); rev[r]=0; } } void build(int &x,int father,int l,int r,dat *str) { //当前x在调用build的时候才建立,,注意根标号是x if(l>r) return ; int mid=l+r>>1; addnode(x,father,str[mid]); build(ch[x][0],x,l,mid-1,str); build(ch[x][1],x,mid+1,r,str); push_up(x); } void init() { root=tot1=tot2=0; ch[0][0]=ch[0][1]=pre[0]=size[0]=rev[0]=0; add[0]=0; minn[0]=INF; addnode(root,0,-1); //在这里创建收尾区间,方便操作 addnode(ch[root][1],root,-1); push_up(ch[root][1]); push_up(root); } void rotate(int x,int kind) { int y=pre[x]; int z=pre[y]; push_down(y); push_down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(z) ch[z][ch[z][1]==y] = x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; push_up(y); } void splay(int r,int goal) { push_down(r); while(pre[r]!=goal) //各类push_down已经在rotate中执行 { if(pre[pre[r]]==goal) { rotate(r,ch[pre[r]][0]==r); continue; } int y=pre[r]; int z=pre[y]; int kind= ch[z][0]==y; if(ch[y][kind]==r) rotate(r,!kind),rotate(r,kind); else rotate(y,kind),rotate(r,kind); } push_up(r); if(goal==0) root=r; } int get_kth(int r,int k) //寻找r根子树下面的第k大 { push_down(r); int t=size[ch[r][0]]+1; if(k==t) return r; if(t>k) return get_kth(ch[r][0],k); return get_kth(ch[r][1],k-t); } void select(int a,int b) //将第a个设为根,第b个设为根的右孩子 { //根的右孩子的左孩子 代表区间[a+1,b-1] splay(get_kth(root,a),0); splay(get_kth(root,b),root); } void ADD(int s,int t,int c) { select(s,t+2); update_add(Key_value,c); push_up(ch[root][1]); push_up(root); } void insert(int pos,int len,dat *str) { select(pos,pos+1); build(Key_value,ch[root][1],0,len-1,str); push_up(ch[root][1]); push_up(root); } void erase(int r) //重复利用删除的结点 { if(!r)return ; s[++tot2]=r; erase(ch[r][0]); erase(ch[r][1]); } void Del(int pos) { select(pos,pos+2); erase(Key_value); pre[Key_value]=0; Key_value=0; push_up(ch[root][1]); push_up(root); } void reverse(int s,int t) //翻转如此就好 { select(s,t+2); update_rev(Key_value); push_up(ch[root][1]); push_up(root); /* select(pos,pos+len+1); rev[key_value]^=1; 这样子写就是错误的 谨记~~~ */ } void dfs(int r,int idx) { if(!r)return ; push_down(r); //必须先push_down, 不然就会更新到新来的点了~~ if(!ch[r][0]) { ch[r][0]=idx; pre[idx]=r; push_up(r); return ; } dfs(ch[r][0],idx); push_up(r); } void revolve(int s,int t,int k) { if(k<=0) k=0; k=k%(t-s+1); if(!k)return ; select(s,t+2); //选取大区间 splay(get_kth(root,t-k+1),ch[root][1]); //选取小区间 int tmp=ch[Key_value][1]; dfs(Key_value,tmp); //维护+移动区间 ch[Key_value][1]=0; //删除区间 push_up(Key_value); //更新 push_up(ch[root][1]); push_up(root); } void get_ans(int s,int t) { select(s,t+2); printf("%d\n",minn[Key_value]); } void InOrder(int r){ //中序 if(r==0) return; push_down(r); InOrder(ch[r][0]); printf("%d ",key[r]); InOrder(ch[r][1]); push_up(r); } }t; int str[MAXN]; int main() { int n,m; int x,y,z; char op[20]; scanf("%d",&n); t.init(); for(int i=0;i<n;i++) scanf("%d",&str[i]); t.insert(1,n,str); scanf("%d",&m); while(m--) { scanf("%s",&op); if(op[0]=='A') { scanf("%d %d %d",&x,&y,&z); t.ADD(x,y,z); } else if(op[0]=='M') { scanf("%d %d",&x,&y); t.get_ans(x,y); } else if(op[0]=='I') { scanf("%d %d",&x,&str[0]); t.insert(x+1,1,str); } else if(op[0]=='D') { scanf("%d",&x); t.Del(x); } else if(op[5]=='S') { scanf("%d %d",&x,&y); t.reverse(x,y); } else if(op[5]=='V') { scanf("%d %d %d",&x,&y,&z); t.revolve(x,y,z); } // t.InOrder(t.root); // cout<<endl; } return 0; }
相关文章推荐
- BZOJ 1895 & POJ 3580 supermemo (splay)
- BZOJ 1895 & POJ 3580 supermemo [SPLAY]【数据结构】
- 【bzoj1895】Pku3580 supermemo Splay
- 【bzoj1895】Pku3580 supermemo
- bzoj1895 Pku3580 supermemo splay
- bzoj1895: Pku3580 supermemo
- [BZOJ 1895]Pku3580 supermemo:Splay
- 【BZOJ1895】Pku3580 supermemo Splay
- [bzoj1895][Pku3580]supermemo_非旋转Treap
- [BZOJ1895]Pku3580 supermemo(splay)
- bzoj1895: Pku3580 supermemo
- BZOJ1895: Pku3580 supermemo Splay
- bzoj1895 Pku3580 supermemo(splay)
- 【splay】【bzoj 1895】: Pku3580 supermemo
- bzoj 1895: Pku3580 supermemo (splay)
- BZOJ_1895_Pku3580 supermemo_Splay
- 【bzoj 1692】【bzoj 1640】【poj 3617】【poj 3623】Best Cow Line 好牛队 双倍经验水水水
- POJ-1895-Bring Them There
- bzoj 3580: 冒泡排序
- POJ 3580 SuperMemo