zoukankan      html  css  js  c++  java
  • BZOJ1251: 序列终结者

    BZOJ1251: 序列终结者

    Description

    网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。

    一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。

    尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……

    这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。

    这道题目 就叫序列终结者吧。

    【问题描述】

    给定一个长度为N的序列,每个序列的元素是一个整数(废话)。

    要支持以下三种操作:

    1. 将[L,R]这个区间内的所有数加上V。

    2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。

    3. 求[L,R]这个区间中的最大值。

    最开始所有元素都是0。

    Input

    第一行两个整数N,M。M为操作个数。

    以下M行,每行最多四个整数,依次为K,L,R,V。

    K表示是第几种操作,如果不是第1种操作则K后面只有两个数。

    Output

    对于每个第3种操作,给出正确的回答。

    Sample Input

    4 4
    1 1 3 2
    1 2 4 -1
    2 1 3
    3 2 4

    Sample Output

    2
    【数据范围】
    N<=50000,M<=100000。
    题解Here!
    刚开始学Splay时,我也是一脸懵——区间翻转咋整?
    然后,我先去做了个更难的题目:BZOJ1500: [NOI2005]维修数列
    于是就会做这题了。。。
    区间 [ l , r ] 翻转也就是将 l-1 伸展到根,将 r+1 伸展到 l-1 的右子树,然后对 r+1 的左子树,即 [ l , r ] 这段区间打上一个区间翻转标记flag。
    下次伸展之前把标记下传一下就好了。
    区间加同理。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 50010
    #define MAX 2147483647
    using namespace std;
    int n,m,root,w[MAXN];
    struct node{
    	int son[2];
    	int f,v,s,flag,c;
    }a[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void pushup(int rt){
    	if(!rt)return;
    	a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+1;
    	a[rt].v=max(w[rt],max(a[a[rt].son[0]].v,a[a[rt].son[1]].v));
    }
    inline void pushdown(int rt){
    	if(!rt)return;
    	if(a[rt].c){
    		if(a[rt].son[0]){a[a[rt].son[0]].c+=a[rt].c;a[a[rt].son[0]].v+=a[rt].c;w[a[rt].son[0]]+=a[rt].c;}
    		if(a[rt].son[1]){a[a[rt].son[1]].c+=a[rt].c;a[a[rt].son[1]].v+=a[rt].c;w[a[rt].son[1]]+=a[rt].c;}
    		a[rt].c=0;
    	}
    	if(a[rt].flag){
    		a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag=0;
    		swap(a[rt].son[0],a[rt].son[1]);
    	}
    }
    inline void turn(int rt,int k){
    	int x=a[rt].f,y=a[x].f;
    	pushdown(x);pushdown(rt);
    	a[x].son[!k]=a[rt].son[k];
    	if(a[rt].son[k])a[a[rt].son[k]].f=x;
    	a[rt].f=y;
    	if(y)a[y].son[a[y].son[1]==x]=rt;
    	a[x].f=rt;
    	a[rt].son[k]=x;
    	pushup(x);pushup(rt);
    }
    void splay(int rt,int ancestry){
    	while(a[rt].f!=ancestry){
    		int x=a[rt].f,y=a[x].f;
    		if(y==ancestry)turn(rt,a[x].son[0]==rt);
    		else{
    			int k=a[y].son[0]==x?1:0;
    			if(a[x].son[k]==rt){turn(rt,!k);turn(rt,k);}
    			else{turn(x,k);turn(rt,k);}
    		}
    	}
    	if(ancestry==0)root=rt;
    	pushup(rt);
    }
    int buildtree(int l,int r,int rt){
    	if(l>r)return 0;
    	int mid;
    	if(l==r){
    		a[l].f=rt;
    		a[l].s=1;
    		return l;
    	}
    	mid=l+r>>1;
    	a[mid].son[0]=buildtree(l,mid-1,mid);
    	a[mid].son[1]=buildtree(mid+1,r,mid);
    	a[mid].f=rt;a[mid].s=1;
    	pushup(mid);
    	return mid;
    }
    int kth(int rt,int x){
    	pushdown(rt);
    	int lsons=0;
    	if(a[rt].son[0])lsons=a[a[rt].son[0]].s;
    	if(x==lsons+1)return rt;
    	if(x<=lsons)return kth(a[rt].son[0],x);
    	else return kth(a[rt].son[1],x-lsons-1);
    }
    int split(int rt,int x,int y){
    	int p=kth(rt,x),q=kth(rt,y);
    	splay(p,0);splay(q,p);
    	return a[q].son[0];
    }
    void work(int rt,int x,int y,int k){
    	int p=kth(rt,x),q=kth(rt,y+2),r;
    	splay(p,0);splay(q,p);
    	r=a[q].son[0];
    	a[r].c+=k;a[r].v+=k;w[r]+=k;
    	pushup(q);pushup(p);
    }
    int main(){
    	int f,x,y,k;
    	n=read();m=read();
    	a[0].v=w[0]=w[1]=w[n+2]=-MAX;
    	root=buildtree(1,n+2,0);
    	while(m--){
    		f=read();x=read();y=read();
    		switch(f){
    			case 1:{
    				k=read();
    				work(root,x,y,k);
    				break;
    			}
    			case 2:{
    				k=split(root,x,y+2);
    				a[k].flag^=1;
    				break;
    			}
    			case 3:{
    				k=split(root,x,y+2);
    				printf("%d
    ",a[k].v);
    				break;
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9368799.html
Copyright © 2011-2022 走看看