【BZOJ】【1251】序列终结者

Splay


  还是splay序列维护,这题我WA了的原因是:在Push_up的时候,当前子树的max我是直接取的L、R和v[x]的最大值,但是如果没有左/右儿子,默认是会访问0号结点的mx值,而这个值没有初始化成-INF,所以就会导致所有负max值全部变为0……

  1 /**************************************************************
  2     Problem: 1251
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:8692 ms
  7     Memory:4888 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 1251
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=1e5+10,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 int a[N],n,m;
 32 int c[N][2],fa[N],v[N],size[N],add[N],mx[N],tot,root;
 33 bool rev[N];
 34 #define L c[x][0]
 35 #define R c[x][1]
 36 void Push_down(int x){
 37     if (rev[x]){
 38         rev[L]^=1; rev[R]^=1;
 39         swap(L,R); rev[x]=0;
 40     }
 41     if (add[x]){
 42         if (L) mx[L]+=add[x]; v[L]+=add[x]; add[L]+=add[x];
 43         if (R) mx[R]+=add[x]; v[R]+=add[x]; add[R]+=add[x];
 44         add[x]=0;
 45     }
 46 }
 47 void Push_up(int x){
 48     mx[x]=max(v[x],max(mx[L],mx[R]));
 49     size[x]=size[L]+size[R]+1;
 50 }
 51 void New_node(int &x,int f,int key){
 52     x=++tot;
 53     fa[x]=f; mx[x]=v[x]=key;
 54     L=R=rev[x]=add[x]=0;
 55     size[x]=1;
 56 }
 57 void Build(int &x,int f,int l,int r){
 58     if (l>r) return;
 59     int m=l+r>>1;
 60     New_node(x,f,a[m]);
 61     Build(L,x,l,m-1);
 62     Build(R,x,m+1,r);
 63     Push_up(x);
 64 }
 65 void Rotate(int x){
 66     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
 67     c[z][c[z][1]==y]=x;
 68     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
 69     c[y][l]=c[x][r]; c[x][r]=y;
 70     Push_up(y);
 71 }
 72 int st[N],top;
 73 void Preview(int x){
 74     top=0; st[++top]=x;
 75     for(;fa[x];x=fa[x])
 76         st[++top]=fa[x];
 77     D(i,top,1) Push_down(st[i]);
 78 }
 79 void splay(int x,int s=0){
 80     int y;
 81     for(Preview(x);fa[x]!=s;Rotate(x))
 82         if (fa[y=fa[x]]!=s)
 83             Rotate( c[y][1]==x^c[fa[y]][1]==y ? x : y);
 84     Push_up(x);
 85     if (!s) root=x;
 86 }
 87 int kth(int x,int k){
 88     Push_down(x);
 89     if (size[L]+1==k) return x;
 90     else if (size[L]>=k) return kth(L,k);
 91     else return kth(R,k-size[L]-1);
 92 }
 93 int main(){
 94 #ifndef ONLINE_JUDGE
 95     freopen("1251.in","r",stdin);
 96     freopen("1251.out","w",stdout);
 97 #endif
 98     n=getint(); m=getint();
 99     a[0]=a[n+1]=-INF; mx[0]=-INF;
100     Build(root,0,0,n+1);
101     int cmd,x,y,z,pos;
102     F(i,1,m){
103         cmd=getint(); x=getint(); y=getint();
104         splay(kth(root,x)); splay(kth(root,y+2),root);
105         pos=c[c[root][1]][0];
106         if (cmd==1){
107             z=getint();
108             add[pos]+=z; v[pos]+=z; mx[pos]+=z;
109             splay(pos);
110         }else if (cmd==2){
111             rev[pos]^=1;
112             splay(pos);
113         }else if (cmd==3){
114             printf("%d\n",mx[pos]);
115             splay(pos);
116         }
117     }
118     return 0;
119 }
View Code

 

1251: 序列终结者

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2798  Solved: 1115
[Submit][Status][Discuss]

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。

HINT

Source

[Submit][Status][Discuss]
posted @ 2015-04-10 12:24  Tunix  阅读(299)  评论(0编辑  收藏  举报