noi 2005维修数列

OI生涯中最想过的一题=v=

splay加上各种各样的操作,样例又不敢拿来调了。。。

感觉指针写splay好难调,所以以后写splay都用数组吧(其实是因为黄大神也用数组orz)

好像是2小时敲完。。debug了2天TAT一开始把操作6和某提混了。。。

然后搞来搞去才发现读入有个毛病0A0

再然后又发现一直以来自己的pushdown和别人是不一样的。。(那些题我居然过了。。。)

最后被内存限制卡住,时间换空间。。(然而本地测试90.。。难道是我的电脑太慢?)

虽然很累,但学了不少,值了

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #define inc(i,l,r) for(i=l;i<=r;i++)
  7 #define dec(i,l,r) for(i=l;i>=r;i--)
  8 #define inf 1e9
  9 #define mem(a) memset(a,0,sizeof(a))
 10 #define ll long long
 11 #define NM 1000000+5
 12 using namespace std;
 13 int read(){
 14     int x=0,f=1;char ch=getchar();
 15     while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
 16     while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
 17     return x*f;
 18 }
 19 int n,m,i,x,t,w[NM];
 20     int root,tot,c[NM][2],f[NM],a[NM],b[NM],L[NM],R[NM],M[NM],val[NM],s[NM],z[NM];
 21     bool v[NM];
 22     queue<int>q;
 23     void newnode(int &r,int fa,int k){
 24         if(!q.empty())r=q.front(),q.pop();else r=++tot;
 25         f[r]=fa;c[r][0]=c[r][1]=0;
 26         b[r]=1;
 27         s[r]=a[r]=M[r]=k;
 28         if(k>0)L[r]=R[r]=k;else L[r]=R[r]=0;
 29         val[r]=v[r]=z[r]=0;
 30     }
 31     void rev(int x){
 32         swap(c[x][0],c[x][1]);swap(L[x],R[x]);z[x]^=1;
 33     }
 34     void ch(int x,int k){
 35         val[x]=a[x]=k;v[x]=1;s[x]=b[x]*val[x];
 36         if(val[x]>0)
 37         L[x]=R[x]=M[x]=s[x];
 38         else L[x]=R[x]=0,M[x]=val[x];
 39     }
 40     void update(int r){
 41         int x=c[r][0],y=c[r][1];
 42         if(x==0)x=tot+1,M[x]=-inf;
 43         if(y==0)y=tot+1,M[y]=-inf;
 44         b[r]=b[x]+b[y]+1;
 45         s[r]=s[x]+s[y]+a[r];
 46         L[r]=max(L[x],s[x]+L[y]+a[r]);
 47         R[r]=max(R[y],R[x]+s[y]+a[r]);
 48         M[r]=max(M[x],M[y]);
 49         M[r]=max(M[r],R[x]+a[r]+L[y]);
 50     }
 51     void pushdown(int x){
 52         if(v[x]){
 53             ch(c[x][0],val[x]);ch(c[x][1],val[x]);
 54             v[x]=0;z[x]=0;
 55         }
 56         if(z[x]){
 57             rev(c[x][0]);rev(c[x][1]);
 58             z[x]=0;
 59         }
 60     }
 61     int d(int x){
 62         return c[f[x]][1]==x;
 63     }
 64     void rot(int x){
 65         int y=f[x],kind=!d(x);
 66         pushdown(c[x][kind]);
 67         c[y][!kind]=c[x][kind];
 68         f[c[x][kind]]=y;
 69         if(f[y])c[f[y]][d(y)]=x;
 70         f[x]=f[y];
 71         c[x][kind]=y;
 72         f[y]=x;
 73         update(y);
 74         update(x);
 75     }
 76     void splay(int x,int goal=0){
 77         for(int y=f[x];y!=goal;y=f[x]){
 78             pushdown(y);pushdown(x);
 79             if(f[y]!=goal)
 80             d(y)==d(x)?rot(y):rot(x);
 81             rot(x);
 82         }
 83         if(goal==0)root=x;
 84     }
 85     int sel(int x){
 86         int r=root;
 87         while(x>0){
 88             pushdown(r);
 89             int t=b[c[r][0]];
 90             if(x==t+1)return r;
 91             if(x>t){
 92                 x-=t+1;r=c[r][1];
 93             }else r=c[r][0];
 94         }
 95     }
 96     int pick(int x,int y){
 97         x++;y++;
 98         y=sel(y);x=sel(x);
 99         splay(x);splay(y,x);
100         return y;
101     }
102     void rec(int x){
103         q.push(x);
104         if(c[x][0])rec(c[x][0]);
105         if(c[x][1])rec(c[x][1]);
106     }
107     void del(int x,int t){
108         x=pick(x-1,x+t);
109         rec(c[x][0]);
110         f[c[x][0]]=0;c[x][0]=0;
111         update(x);
112         splay(x);
113     }
114     int sum(int x,int t){
115         x=pick(x-1,x+t);
116         return s[c[x][0]];
117     }
118     int link(){
119         int r=root;
120         pushdown(c[r][0]);pushdown(c[r][1]);
121         update(r);
122         return M[r];
123     }
124     void build(int x,int y,int fa,int &r){
125         int t=x+y>>1;
126         if(x>y)return;
127         newnode(r,fa,w[t]);
128         build(x,t-1,r,c[r][0]);
129         build(t+1,y,r,c[r][1]);
130         update(r);
131     }
132     void ins(int x,int t){
133         int i;
134         x=pick(x,x+1);
135         inc(i,1,t)w[i]=read();
136         build(1,t,x,c[x][0]);
137         update(x);
138         splay(c[x][0]);
139     }
140 int main(){
141 //    freopen("sequence.in","r",stdin);
142 //    freopen("sequence.ans","w",stdout);
143     n=read();m=read();
144     newnode(root,0,-inf);newnode(c[root][1],root,-inf);update(root);
145     ins(0,n);
146     inc(i,1,m){
147         char s=getchar();
148         while(s<‘A‘||s>‘Z‘)s=getchar();
149         s=getchar();s=getchar();
150         if(s==‘X‘){
151         printf("%d\n",link());
152         while((‘A‘<=s&&s<=‘Z‘)||s==‘-‘)s=getchar();
153         }
154         else{
155             getchar();getchar();
156             x=read();t=read();
157             if(s==‘L‘)del(x,t);
158             else if(s==‘T‘)printf("%d\n",sum(x,t));
159             else if(s==‘V‘){
160                 x=pick(x-1,x+t);
161                 x=c[x][0];
162                 if(v[x])continue;
163                 rev(x);
164                 pushdown(x);
165                 splay(x);
166             }
167             else if(s==‘K‘){
168                 x=pick(x-1,x+t);
169                 x=c[x][0];
170                 val[x]=read();v[x]=1;
171                 ch(x,val[x]);
172                 pushdown(x);
173                 splay(x);
174             }
175             else ins(x,t);
176         }
177     }
178     return 0;
179 }

时间: 2024-10-12 18:41:48

noi 2005维修数列的相关文章

BZOJ 1500 NOI 2005 维修数列 Splay

题意:见下图 传说级别的NOI数据结构神题,像我这种弱渣花了一下午的时间才A掉,最后发现竟然是边界值的问题没处理好.. 这个题对Splay的所有操作基本是全了. 插入:新建一颗Splay Tree,然后把对应节点Splay到根的右儿子上,再把新建的树连上. 删除:把要删除的区间Splay到根的右儿子的左儿子上,递归free掉.(这里可以用数组优化,可以避免递归free节省时间) 修改,翻转:打标记,在需要的时候下传标记,和线段树差不多,翻转标记下传时,要将左右儿子的左右儿子分别交换. 求和:维护

bzoj 1500 [NOI 2005] 维修数列

题目大意不多说了 貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧 还是有很多操作的,估计够以后当模版了.... 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 7 using namespace std; 8 const int N = 1000010; 9 cons

NOI 2005 维修数列

妈妈呀我终于过了!!!原来是数据坑我!!! 弃疗弃疗弃疗弃疗!!!!我调了一天呢....被GET_SUM 8 0打败了.... 啥也不说了....还是我太年轻.... 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU put

NOI 2005维护数列

题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目. 第 2 行包含 N 个数字,描述初始时的数列. 以下 M 行,每行一条命令,格式参见问题描述中的表格 输出格式: 对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结 果,每个答案(数字)占一行. SOL: 我们发

1500: [NOI2005]维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12952  Solved: 4138[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ1500: [NOI2005]维修数列[splay ***]

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ 1500: [NOI2005]维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12880  Solved: 4112[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,

BZOJ1500 维修数列

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内.插入的数字总数不超过4 000 000个,输入文

bzoj1500 维修数列 splay

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 10482  Solved: 3234[Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格.任何时刻数列中最多含有500 000个数,