bzoj1500 维修序列

OI生涯中印象最深一题 一直被卡0。。

  1 #include<bits/stdc++.h>
  2 #define clr(a,x) memset(a,x,sizeof(a))
  3 #define rep(i,l,r) for(int i=l;i<r;i++)
  4 #define lowbit(a) ((a)&(-(a)))
  5 typedef long long ll;
  6 typedef unsigned long long ul;
  7 using namespace std;
  8 int read(){
  9     int ans=0,f=1;
 10     char c=getchar();
 11     while(!isdigit(c)){
 12         if(c==‘-‘) f=-1;
 13         c=getchar();
 14     }
 15     while(isdigit(c)){
 16         ans=ans*10+c-‘0‘;
 17         c=getchar();
 18     }
 19     return ans*f;
 20 }
 21 const int maxn=550000,inf=1e9;
 22 struct node*null;
 23 struct node{
 24     int v,sum,maxl,maxr,mx,s,set;
 25     bool rev;
 26     node*ch[2];
 27     inline int cmp(int k){
 28         k-=ch[0]->s;
 29         if(k==1) return -1;
 30         return (k<=0)?0:1;
 31     }
 32     inline void maintain(){
 33         s=ch[0]->s+ch[1]->s+1;
 34         sum=ch[0]->sum+ch[1]->sum+v;
 35         maxl=max(ch[0]->maxl,ch[0]->sum+v+max(0,ch[1]->maxl));
 36         maxr=max(ch[1]->maxr,ch[1]->sum+v+max(0,ch[0]->maxr));
 37         mx=max(ch[0]->mx,ch[1]->mx);
 38         mx=max(mx,max(0,ch[0]->maxr)+v+max(0,ch[1]->maxl));
 39     }
 40     inline void Set(int k){
 41         set=k;
 42         v=k;
 43         sum=s*k;
 44         mx=maxl=maxr=k*(k>0?s:1);
 45     }
 46     inline void Rev(){
 47         rev^=1;
 48         swap(ch[0],ch[1]);
 49         swap(maxl,maxr);
 50     }
 51     inline void pushdown(){
 52         if(set!=inf){
 53             if(ch[0]!=null) ch[0]->Set(set);
 54             if(ch[1]!=null) ch[1]->Set(set);
 55             set=inf;
 56             rev=0;
 57         }
 58         if(rev){
 59             rev=0;
 60             if(ch[0]!=null) ch[0]->Rev();
 61             if(ch[1]!=null) ch[1]->Rev();
 62         }
 63     }
 64 };
 65 int pos,tot,n,m,a[maxn];
 66 node x[maxn],*root;
 67 queue<node*>Q;
 68 node*newnode(int k){
 69     node*o=Q.front();Q.pop();
 70     o->ch[0]=o->ch[1]=null;
 71     o->s=1;
 72     o->set=inf;
 73     o->rev=0;
 74     o->v=o->sum=o->maxl=o->maxr=o->mx=k;
 75     return o;
 76 }
 77 void rot(node*&o,int d){
 78     o->pushdown();
 79     node*k=o->ch[d^1];
 80     k->pushdown();
 81     o->ch[d^1]=k->ch[d];
 82     k->ch[d]=o;
 83     o->maintain();k->maintain();
 84     o=k;
 85 }
 86 void splay(node*&o,int k){
 87     o->pushdown();
 88     int d=o->cmp(k);
 89     if(d==-1) return;
 90     if(d==1) k-=o->ch[0]->s+1;
 91     node*p=o->ch[d];
 92     p->pushdown();
 93     int d1=p->cmp(k);
 94     int k1=(d1)?k-p->ch[0]->s-1:k;
 95     if(d1!=-1){
 96         splay(p->ch[d1],k1);
 97         (d==d1)?rot(o,d^1):rot(o->ch[d],d);
 98     }
 99     rot(o,d^1);
100 }
101 node*build(int l,int r){
102     if(l>=r) return null;
103     int mid=(l+r)>>1;
104     node*o=newnode(a[mid]);
105     if(l<mid) o->ch[0]=build(l,mid);
106     if(r>mid+1) o->ch[1]=build(mid+1,r);
107     o->maintain();
108     return o;
109 }
110 void ins(){
111     node*o=build(1,tot+1);
112     splay(root,pos+1);
113     splay(root->ch[1],pos+1-root->ch[0]->s);
114     root->ch[1]->ch[0]=o;
115     root->ch[1]->maintain();root->maintain();
116 }
117 void del(node*o){
118     if(o==null) return;
119     del(o->ch[0]);
120     del(o->ch[1]);
121      Q.push(o);
122 }
123 void init(){
124     rep(i,0,maxn) Q.push(x+i);
125     null=newnode(0);
126     null->s=0;
127     null->maxl=null->maxr=null->mx=null->v=-inf;
128     root=build(0,n+2);
129 }
130 void dfs(node*o){
131     if(o==null) return;
132     o->pushdown();
133     dfs(o->ch[0]);
134     printf("%d ",o->mx);
135     dfs(o->ch[1]);
136 }
137 int main()
138 {
139     n=read(),m=read();
140     rep(i,1,n+1) a[i]=read();
141     a[0]=a[n+1]=-inf;
142     init();
143     while(m--){
144         char c[15];
145         scanf(" %s",c);
146         if(c[0]==‘I‘){
147             pos=read(),tot=read();
148             clr(a,0);
149             rep(i,1,tot+1) a[i]=read();
150             ins();
151         }else if(c[0]==‘D‘){
152             pos=read(),tot=read();
153             splay(root,pos);
154             splay(root->ch[1],pos+tot-root->ch[0]->s);
155             del(root->ch[1]->ch[0]);
156             root->ch[1]->ch[0]=null;
157             root->ch[1]->maintain();root->maintain();
158         }else if(c[0]==‘R‘){
159             pos=read(),tot=read();
160             splay(root,pos);
161             splay(root->ch[1],pos+tot-root->ch[0]->s);
162             root->ch[1]->ch[0]->Rev();
163             root->ch[1]->maintain();root->maintain();
164         }else if(c[0]==‘G‘){
165             pos=read(),tot=read();
166             splay(root,pos);
167             splay(root->ch[1],pos+tot-root->ch[0]->s);
168             printf("%d\n",root->ch[1]->ch[0]->sum);
169         }else if(c[2]==‘K‘){
170             pos=read(),tot=read();
171             int t=read();
172             splay(root,pos);
173             splay(root->ch[1],pos+tot-root->ch[0]->s);
174             root->ch[1]->ch[0]->Set(t);
175             root->ch[1]->maintain();root->maintain();
176         }else{
177             printf("%d\n",root->mx);
178         }
179     }
180     return 0;
181 }

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 8501  Solved: 2563
[Submit][Status][Discuss]

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

Output

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

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
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

Sample Output

-1
10
1
10

HINT

Source

Splay

时间: 2024-10-05 03:54:10

bzoj1500 维修序列的相关文章

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个数,

【bzoj1500 维修数列】(NOI2005)

真的是太弱了TAT...光是把代码码出来就花了3h..还调了快1h才弄完T_T 号称考你会不会splay(当然通过条件是1h内AC..吓傻)... 黄学长的题解:http://hzwer.com/2841.html 当然了蒟蒻的splay模板全部都是借(抄)鉴(袭)黄学长的.... 主要是注意任何对子树的修改一定要记得pushup一定要记得pushup一定要记得pushup...计算最大子段和和bzoj1858一个姿势,就是维护子树的最大子段和,从左和从右开始的最大子段和(当然了平衡树和线段树在

bzoj1251: 序列终结者 (splay)

splay可以用于维护序列,比如noi的维修序列,比如这道 发现当时splay没写总结,也没题解 然后重新写splay竟然耗了一个晚上 结果是因为max[0]没有附最小值!!血一样的教训 最后祭出inline大法才过,我的splay真的慢到吐血 {$inline on} {$M 1000000000,0,maxlongint} const //mm=maxlongint>>2; maxn=60000; var size,left,right,mark,fa,value,max:array[0.

fhq treap

fhq-treap 小结 粗浅地学习了这个神奇的数据结构,下面瞎写一些感受 首先fhq treap是一个基于分裂与合并的平衡树,那么怎么分裂,怎么合并呢 我们分两种情况考虑 一.权值平衡树(我自己取的名字) 所谓权值平衡树,就是任何操作都只与权值有关的平衡树 比如最基础的分裂,合并操作 分裂就是把平衡树按照权值\(k\)分成两半,一边所有点的权值\(\leq k\),另一边权值\(\gt k\) 怎么分裂呢 首先根据\(treap\)的定义,所有点的权值是一颗二叉搜索树(BST),就是左边比他小

Splay小结

有关论文: 运用伸展树解决数列维护问题 算法合集之<伸展树的基本操作与应用> splay的伸展操作 splay(x,goal)将x节点移到goal节点的下方,通过左旋和右旋基本操作实现,其实现过程在论文中有详细介绍. 对于用splay去维护一个数列,有以下常用操作. 1.splay(x,goal) 将结点k旋转到goal结点的下方 2.getpos(x) 查询第x个节点的在树中的位置. 3.rotateto(x,goal) 将第x个结点旋转到goal结点下方,可以由 rotateto(x,go

poj3580 SuperMemo

SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12273   Accepted: 3887 Case Time Limit: 2000MS Description Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game

Python 练习实例24

Python 练习实例24 题目:有一分数家电维修序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和. 程序分析:请抓住分子与分母的变化规律. 程序源代码: 方法一: 方法二: 方法三: 以上实例输出结果为: 原文地址:https://www.cnblogs.com/danjiu/p/12202487.html

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个数,