COJ WZJ的数据结构(负十八)splay_tree的天堂

WZJ的数据结构(负十八)
难度级别:E; 运行时间限制:100000ms; 运行空间限制:700KB; 代码长度限制:2000000B

试题描述

对于前一段样例:


输入

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。 
第2行包含N个数字,描述初始时的数列。 
以下M行,每行一条命令,格式参见问题描述中的表格。为了考察垃圾回收的使用,我们精心准备了多组数据。。。

输出

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。 

输入示例

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 0
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
3 3
1 2 3
MAKE-SAME 1 3 3
MAX-SUM
MAX-SUM

输出示例

-1
10
1
10
9
9

其他说明

样例见题目图片。
你可以认为在任何时刻,数列中至少有1个数。 
输入数据一定是正确的,即指定位置的数在数列中一定存在。  
50%的数据中,任何时刻数列中最多含有100个数; 100%的数据中,任何时刻数列中最多含有500个数。  
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。 
100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
注意内存限制。请块状链表选手自重;由于数据不太好请Splay选手谨慎使用双旋。

题解:注意内存的妥善利用。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #define PAU putchar(‘ ‘)
  8 #define ENT putchar(‘\n‘)
  9 #define CH for(int d=0;d<=1;d++) if(ch[d])
 10 using namespace std;
 11 const int maxn=500+10,inf=-1u>>1;
 12 int max(int a,int b,int c){return max(a,max(b,c));}
 13 struct node{
 14     node*fa,*ch[2];
 15     int x;bool rev;int siz,sm,set,lx,rx,mx;
 16     node(){ch[0]=ch[1]=NULL;x=sm=0;lx=rx=mx=-inf;set=inf;rev=false;siz=1;}
 17     void init(){ch[0]=ch[1]=NULL;x=sm=0;lx=rx=mx=-inf;set=inf;rev=false;siz=1;return;}
 18     void revt(){swap(ch[0],ch[1]);swap(lx,rx);rev^=1;return;}
 19     void sett(int tag){x=set=tag;sm=tag*siz;lx=rx=mx=max(tag,tag*siz);return;}
 20     void update();
 21     void down(){
 22         if(rev){CH{ch[d]->revt();}rev=false;}
 23         if(set!=inf){CH{ch[d]->sett(set);}set=inf;}
 24         return;
 25     }
 26 }Splay[maxn],*root;int nodecnt=0;
 27 queue<node*>RAM;
 28 node*newnode(){
 29     node*t;if(!RAM.empty()) t=RAM.front(),RAM.pop();
 30     else t=&Splay[nodecnt++];t->init();return t;
 31 }
 32 void del(node*&x){RAM.push(x);return;}
 33 void deltree(node*&x){
 34     if(!x)return;deltree(x->ch[0]);deltree(x->ch[1]);del(x);return;
 35 }
 36 void copy(node*&x,node*y){
 37     x->x=y->x;
 38     x->lx=y->lx;
 39     x->mx=y->mx;
 40     x->rx=y->rx;
 41     x->sm=y->sm;
 42     x->siz=y->siz;
 43     x->set=y->set;
 44     x->rev=y->rev;
 45     return;
 46 }
 47 void node::update(){
 48     siz=1;sm=x;lx=mx=rx=0;node*n[2];n[0]=newnode();n[1]=newnode();
 49     CH{siz+=ch[d]->siz;sm+=ch[d]->sm;copy(n[d],ch[d]);}
 50     lx=max(n[0]->lx,n[0]->sm+x+max(0,n[1]->lx));
 51     rx=max(n[1]->rx,n[1]->sm+x+max(0,n[0]->rx));
 52     mx=max(0,n[0]->rx)+x+max(0,n[1]->lx);
 53     mx=max(n[0]->mx,n[1]->mx,mx);
 54     del(n[0]);del(n[1]);
 55     return;
 56 }
 57 int parent(node*x,node*&y){return (y=x->fa)?y->ch[1]==x?1:y->ch[0]==x?0:-1:-1;}
 58 void rotate(node*x){
 59     node*y,*z;int d1=parent(x,y),d2=parent(y,z);
 60     if(y->ch[d1]=x->ch[d1^1]) y->ch[d1]->fa=y;
 61     y->fa=x;x->fa=z;x->ch[d1^1]=y;
 62     if(d2!=-1) z->ch[d2]=x;
 63     y->update();return;
 64 }
 65 void pushdown(node*x){
 66     static node*s[maxn];int top=0;
 67     for(node*y;;x=y){
 68         s[top++]=x;y=x->fa;
 69         if(!y||(y->ch[0]!=x&&y->ch[1]!=x)) break;
 70     } while(top--) s[top]->down();return;
 71 }
 72 node*splay(node*x){
 73     pushdown(x);node*y,*z;int d1,d2;
 74     while(true){
 75         if((d1=parent(x,y))<0) break;
 76         if((d2=parent(y,z))<0){rotate(x);break;}
 77         if(d1==d2) rotate(y),rotate(x);
 78         else rotate(x),rotate(x);
 79     } x->update();return x;
 80 }
 81 node*find(node*x,int rank){
 82     x->down();int kth=1;if(x->ch[0]) kth=x->ch[0]->siz+1;
 83     if(rank==kth) return x;
 84     if(rank<kth) return find(x->ch[0],rank);
 85     else return find(x->ch[1],rank-kth);
 86 }
 87 void split(node*&x,node*&y,int a){
 88     if(!a){y=x;x=NULL;return;}
 89     x=splay(find(x,a));y=x->ch[1];
 90     x->ch[1]=NULL;if(y)y->fa=NULL;x->update();return;
 91 }
 92 void split(node*&x,node*&y,node*&z,int a,int b){
 93     split(x,z,b);split(x,y,a-1);return;
 94 }
 95 void join(node*&x,node*y){
 96     if(!x){x=y;return;}if(!y)return;
 97     x=splay(find(x,x->siz));x->ch[1]=y;
 98     if(y)y->fa=x;x->update();return;
 99 }
100 void join(node*&x,node*y,node*z){
101     join(y,z);join(x,y);return;
102 }
103 inline int read(){
104     int x=0,sig=1;char ch=getchar();
105     while(!isdigit(ch)){if(ch==‘-‘)sig=-1;ch=getchar();}
106     while(isdigit(ch))x=10*x+ch-‘0‘,ch=getchar();
107     return x*sig;
108 }
109 inline void write(int x){
110     if(x==0){putchar(‘0‘);return;}if(x<0)putchar(‘-‘),x=-x;
111     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
112     for(int i=len-1;i>=0;i--)putchar(buf[i]+‘0‘);return;
113 }
114 int s[maxn];
115 void build(node*&x,int L,int R){
116     if(L>R)return;int M=L+R>>1;
117     x=newnode();x->x=s[M];
118     build(x->ch[0],L,M-1);
119     build(x->ch[1],M+1,R);
120     if(x->ch[0]) x->ch[0]->fa=x;
121     if(x->ch[1]) x->ch[1]->fa=x;
122     x->update();return;
123 }
124 void insert(int pos,int num){
125     int ms=0;for(int i=0;i<num;i++) s[ms++]=read();
126     node*x,*y;build(x,0,num-1);
127     split(root,y,pos);join(root,x,y);return;
128 }
129 void remove(int L,int R){
130     node*x,*y;split(root,x,y,L,R);deltree(x);join(root,y);return;
131 }
132 void settag(int L,int R,int tag){
133     node*x,*y;split(root,x,y,L,R);x->sett(tag);join(root,x,y);return;
134 }
135 int getsum(int L,int R){
136     node*x,*y;split(root,x,y,L,R);int sm=x->sm;join(root,x,y);return sm;
137 }
138 int getssm(int L,int R){
139     node*x,*y;split(root,x,y,L,R);int mx=x->mx;join(root,x,y);return mx;
140 }
141 void reverse(int L,int R){
142     node*x,*y;split(root,x,y,L,R);x->revt();join(root,x,y);return;
143 }
144 void init(){
145     int n,Q;int pos,k,v;char str[15];
146     while(scanf("%d%d",&n,&Q)==2){
147         for(int i=0;i<n;i++) s[i]=read();build(root,0,n-1);
148         while(Q--){
149             scanf("%s",str);
150             if(str[0]==‘I‘){
151                 pos=read();k=read();
152                 insert(pos,k);
153             }
154             else if(str[0]==‘D‘){
155                 pos=read();k=read();
156                 remove(pos,pos+k-1);
157             }
158             else if(!strcmp(str,"MAKE-SAME")){
159                 pos=read();k=read();v=read();
160                 settag(pos,pos+k-1,v);
161             }
162             else if(!strcmp(str,"REVERSE")){
163                 pos=read();k=read();
164                 reverse(pos,pos+k-1);
165             }
166             else if(!strcmp(str,"GET-SUM")){
167                 pos=read();k=read();
168                 if(!k){puts("0");continue;}
169                 write(getsum(pos,pos+k-1));ENT;
170             }
171             else write(getssm(1,root->siz)),ENT;
172         } deltree(root);
173     }
174     return;
175 }
176 void work(){
177     return;
178 }
179 void print(){
180     return;
181 }
182 int main(){init();work();print();return 0;}
时间: 2024-12-08 09:22:20

COJ WZJ的数据结构(负十八)splay_tree的天堂的相关文章

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

18. 蛤蟆的数据结构进阶十八排序实现之快速排序

18. 蛤蟆的数据结构进阶十八排序实现之快速排序 本篇名言:"一个人做点好事并不难,难的是一辈子做好事,不做坏事.--毛泽东" 我们最后来看下快速排序,以及各个排序之间的一些信息汇总. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47817933 1.  快速排序 快速排序由C. A. R.Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分

COJ WZJ的数据结构(负三十三)

WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行N次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v. 输入 第一行为一个正整数N.第二行为N个整数Ai.接下来N行每行4个正整数t,l,r,v.若t=2表

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树

COJ966 WZJ的数据结构(负三十四)

WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u r"的Q个询问, 回答以 u 节点为中心,半径 r 以内的节点中,权值最大的节点的编号是多少.如果有多个节点,返回编号最小的. 输入 共有一组测试数据.第一行包含一个整数 n (1 ≤ n ≤ 10^5),表示节点总数.接下来的一行,包含 n 个数字,表示每个节点的权值 vi (1 ≤ vi ≤ 1

COJ0986:WZJ的数据结构(负十四)

WZJ的数据结构(负十四) 难度级别:D: 运行时间限制:6000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,M次操作,操作分两种: 1.1 i j k 每次询问给你i,j,k三个参数,求Ai至Aj中第k小的数. 2.0 x v 每次操作给你x,v两个参数,将A[x]改成v. 输入 第一行为两个正整数N,M.第二行为N个正整数Ai.接下来M行为操作. 输出 对于每个询问输出答案(保证k合法)

COJ968 WZJ的数据结构(负三十二)

WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着.请你设计一个数据结构,回答M次操作. 1 x:将节点x上的灯拉一次,即亮变灭,灭变亮. 2 x k:询问当前所有亮灯的节点中距离x第k小的距离(注意如果x亮着也算入). 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi