zoukankan      html  css  js  c++  java
  • [POJ3580]SuperMemo

    Description
    给出一个初始序列A1,A2,...,An,要求你编写程序支持如下操作:

    1. ADD x y D:给子序列Ax...Ay的每个元素都加上D。例如对1,2, 3,4,5执行"ADD 2 4 1" 会得到1,3,4,5,5。
    2. REVERSE x y:将子序列Ax...Ay翻转。例如对1,2,3,4,5执行"REVERSE 2 4"会得到1,4,3,2,5。
    3. REVOLVE x y T:将子序列Ax...Ay旋转T个单位。例如,对1,2,3,4,5执行"REVOLVE 2 4 2"会得到1,3,4,2,5。
    4. INSERT x P:在Ax后插入P。例如,对1,2,3,4,5执行"INSERT 2 4"会得到1,2,4,3,4,5。
    5. DELETE x:删去Ax。例如,对1,2,3,4,5执行"DELETE 2"会得到1,3,4,5。
    6. MIN x y:查询子序列Ax...Ay中的最小元素。例如,对于序列1, 2,3,4,5,询问"MIN 2 4"的返回应为2。

    Input
    第一行包含一个整数n,表示初始序列的长度。
    以下n行每行包含一个整数,描述初始的序列。
    接下来一行包含一个整数m,表示操作的数目。以下m行每行描述一个操作。n,m<=10^6

    Output
    对于所有"MIN"操作,输出正确的答案,每行一个。

    Sample Input
    5
    1
    2
    3
    4
    5
    2
    ADD 2 4 1
    MIN 4 5

    Sample Output
    5


    [NOI2005]维修数列差不多,插入删除什么的都不用建树了,查找只要找MIN,除了REVOLVE麻烦点之外,其余并不难

    找前驱后继的时候要记得pushdown,被坑了。。。

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x3fffffff
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)     print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e6;
    int stack[N+10],top,v[N+10];
    struct Splay{
    	#define T(x) (tree[f[x]][1]==x)
    	#define ls(x) tree[x][0]
    	#define rs(x) tree[x][1]
    	int tree[N+10][2],f[N+10],size[N+10],val[N+10],Min[N+10],cnt[N+10];
    	bool rev[N+10];
    	int root,len;
    	void rev_tag(int x){
    		if (!x)	return;
    		swap(ls(x),rs(x));
    		rev[x]^=1;
    	}
    	void cnt_tag(int x,int v){
    		if (!x)	return;
    		cnt[x]+=v,val[x]+=v,Min[x]+=v;
    	}
    	void pushdown(int x){
    		if (cnt[x]){
    			cnt_tag(ls(x),cnt[x]);
    			cnt_tag(rs(x),cnt[x]);
    			cnt[x]=0;
    		}
    		if (rev[x]){
    			rev_tag(ls(x));
    			rev_tag(rs(x));
    			rev[x]=0;
    		}
    	}
    	void updata(int x){
    		size[x]=size[ls(x)]+size[rs(x)]+1;
    		Min[x]=val[x];
    		if (ls(x))	Min[x]=min(Min[x],Min[ls(x)]);
    		if (rs(x))	Min[x]=min(Min[x],Min[rs(x)]);
    	}
    	int get(){
    		int x;
    		x=top?stack[top--]:++len;
    		val[x]=Min[x]=inf;
    		ls(x)=rs(x)=f[x]=0;
    		size[x]=1;
    		cnt[x]=rev[x]=0;
    		return x;
    	}
    	void build(int fa,int l,int r,int &x){
    		if (l>r)	return;
    		int mid=(l+r)>>1;
    		x=get(),f[x]=fa,val[x]=Min[x]=v[mid];
    		build(x,l,mid-1,ls(x)),
    		build(x,mid+1,r,rs(x));
    		updata(x);
    	}
    	void init(int n){
    		val[0]=Min[0]=inf;
    		root=1,len=2;
    		rs(1)=size[1]=2,Min[1]=val[1]=inf;
    		f[2] =size[2]=1,Min[2]=val[2]=inf;
    		for (int i=1;i<=n;i++)	v[i]=read();
    		build(2,1,n,ls(2));
    		updata(2),updata(1);
    	}
    	void move(int x){
    		pushdown(x);
    		int fa=f[x],son=tree[x][T(x)^1];
    		tree[x][T(x)^1]=fa;
    		tree[fa][T(x)]=son;
    		if (son)	f[son]=fa;
    		f[x]=f[fa];
    		if (f[x])	tree[f[x]][T(fa)]=x;
    		f[fa]=x;
    		updata(fa),updata(x);
    	}
    	void splay(int x){
    		while (f[x]){
    			if (f[f[x]])	T(x)==T(f[x])?move(f[x]):move(x);
    			move(x);
    		}
    		root=x;
    	}
    	int find(int x,int i){
    		pushdown(i);
    		if (size[ls(i)]+1==x)	return i;
    		if (x<=size[ls(i)])	return find(x,ls(i));
    		return find(x-size[ls(i)]-1,rs(i));
    	}
    	int get_suc(){
    		int x=rs(root);
    		pushdown(x);
    		while (ls(x))	pushdown(x),x=ls(x);
    		return x;
    	}
    	void insert(){
    		int x=read(),v=read(),t=get();
    		x=find(x+1,root),splay(x);
    		splay(get_suc());
    		f[rs(x)=t]=x;
    		val[t]=Min[t]=v;
    		updata(x),updata(root);
    	}
    	void ADD(){
    		int x=read(),y=read(),v=read();
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		cnt_tag(rs(x),v);
    		updata(x),updata(y);
    	}
    	void filp(){
    		int x=read(),y=read();
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		rev_tag(rs(x));
    	}
    	void Delete(){
    		int x=read(),y=x;
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		stack[++top]=rs(x);
    		f[rs(x)]=0,rs(x)=0;
    		updata(x),updata(y);
    	}
    	void revolve(){
    		int l=read(),y=read(),len=y-l+1,t=read()%len,x=y-t+1;
    		if (!t)	return;
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		int son=rs(x);
    		f[rs(x)]=0,rs(x)=0;
    		updata(x),updata(y);
    		
    		l=find(l,root),splay(l);
    		splay(get_suc());
    		rs(l)=son,f[son]=l;
    		updata(l),updata(root);
    	}
    	void query(){
    		int x=read(),y=read();
    		x=find(x,root),splay(x);
    		y=find(y+2,root),splay(y);
    		if (f[x]!=root)	move(x);
    		printf("%d
    ",Min[rs(x)]);
    	}
    }T;
    char s[10];
    int main(){
    	int n=read();
    	T.init(n);
    	int m=read();
    	for (int i=1;i<=m;i++){
    		memset(s,0,sizeof(s));
    		scanf("%s",s);
    		if (s[0]=='A')	T.ADD();
    		if (s[0]=='M')	T.query();
    		if (s[0]=='I')	T.insert();
    		if (s[0]=='D')	T.Delete();
    		if (s[5]=='S')	T.filp();
    		if (s[5]=='V')	T.revolve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    bzoj 2456 mode
    codeforces 630 I(规律&&组合)
    codeforces 630H (组合数学)
    codeforces 651A Joysticks
    codeforces 651B Beautiful Paintings
    codeforces 625C K-special Tables
    codeforces 630F Selection of Personnel(组合数)
    codeforce 630N Forecast
    后缀数组模板
    Hdu5737-Differencia(有序表线段树)
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9481168.html
Copyright © 2011-2022 走看看