平衡树并不是之前没写过,觉得有必要把平衡树变成考场上能敲的东西,也就是说,考一道诸如“维修数列”这样的送分题,要能拿满分。

维修数列。给定一个数列支持以下操作:

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

以上都是复制的。

这一次呢肯定比上一次敲的快了那么一点,但没有达到要求,总时间大概3h,还需很大的提升。

调试时间。。inf

主要的调试时间在边界的处理上。

1、某个子树大小。本来子树大小如果不影响答案计算的话是可以直接把边界加进来的,但是这里有求和和区间赋值,因此有必要知道区间除了边界外的真实大小。

这一次的处理方式是:假设边界点是不存在的,即size=0.这样引发的一系列调整如下:

首先,up时size的更新要注意不要加上边界点:

a[x].size=a[p].size+a[q].size+(x!=lbod && x!=rbod);

其次,find时对边界点单独处理下:

        if (K>a[root].size) ans=rbod;
else if (K==) ans=lbod;

在find时,找第K个数,如果往右走要这么写:

K-=a[x].size-a[a[x].son[]].size,x=a[x].son[];

而不要写K-=a[a[x].son[0]].size+1,这样相当于默认x的size是1,而x有可能是边界点。

2、连边必up,访子必down。up和down在一些细节会忘了打。最典型的是splay:splay(x,top)表示把x旋到top下,如果top不为0的话应up(top);再如find以及其他类似操作时心存侥幸以为不用down,但实际上这题有区间翻转操作,左右儿子会变,因此必须down。

3、读入。注意'-'号。

4、答案。注意边界点既要做到能传递区间答案,本身又不能对答案产生影响。这里解决的方法是在up的时候进行如下判断:

        if (x!=lbod && x!=rbod) a[x].Maxsum=max(a[p].Maxsum,max(a[q].Maxsum,a[p].rsum+a[x].v+a[q].lsum));
else if (x==lbod) a[x].Maxsum=q?a[q].Maxsum:-0x3f3f3f3f;
else a[x].Maxsum=p?a[p].Maxsum:-0x3f3f3f3f;

以及在区间赋值时进行如下操作:

        if (x==lbod || x==rbod) a[x].v=;
if (a[x].size==) a[x].lsum=a[x].rsum=a[x].Maxsum=-0x3f3f3f3f;

调试时果断选择区间输出。但静态查错还是不能少。

总的来说,有待提高。

 #include<string.h>
#include<stdlib.h>
#include<stdio.h>
//#include<assert.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m;
#define maxn 500011
int num[maxn]; struct Splay
{
struct Node
{
int son[],fa;
bool rev,hbe; int be;
int v,size,sum,Maxsum,lsum,rsum;
}a[maxn];
int root,sta[maxn],top,lbod,rbod;
Splay()
{
top=;
for (int i=;i<=top;i++) sta[i]=i;
root=lbod=; rbod=;
a[].Maxsum=-0x3f3f3f3f;
a[lbod].Maxsum=a[rbod].Maxsum=a[lbod].lsum=a[lbod].rsum=a[rbod].lsum=a[rbod].rsum=-0x3f3f3f3f;
a[lbod].v=a[lbod].size=a[lbod].sum=a[lbod].rev=a[lbod].hbe=;
a[rbod].v=a[rbod].size=a[rbod].sum=a[rbod].rev=a[rbod].hbe=;
a[lbod].son[]=rbod; a[rbod].fa=lbod;
}
void up(int x)
{
if (!x) return;
int &p=a[x].son[],&q=a[x].son[];
a[x].sum=a[p].sum+a[q].sum+a[x].v;
a[x].size=a[p].size+a[q].size+(x!=lbod && x!=rbod);
if (x!=lbod && x!=rbod) a[x].Maxsum=max(a[p].Maxsum,max(a[q].Maxsum,a[p].rsum+a[x].v+a[q].lsum));
else if (x==lbod) a[x].Maxsum=q?a[q].Maxsum:-0x3f3f3f3f;
else a[x].Maxsum=p?a[p].Maxsum:-0x3f3f3f3f;
a[x].lsum=max(a[p].lsum,a[p].sum+a[x].v+a[q].lsum);
a[x].rsum=max(a[q].rsum,a[q].sum+a[x].v+a[p].rsum);
}
void besingle(int x,int v)
{
if (!x) return;
a[x].v=a[x].be=v; a[x].hbe=;
if (x==lbod || x==rbod) a[x].v=;
a[x].sum=a[x].size*v;
if (v>=) a[x].lsum=a[x].rsum=a[x].Maxsum=a[x].sum;
else a[x].lsum=a[x].rsum=,a[x].Maxsum=v;
if (a[x].size==) a[x].lsum=a[x].rsum=a[x].Maxsum=-0x3f3f3f3f;
}
void revsingle(int x)
{
if (!x) return;
a[x].rev^=; int t=a[x].son[]; a[x].son[]=a[x].son[]; a[x].son[]=t;
t=a[x].lsum; a[x].lsum=a[x].rsum; a[x].rsum=t;
}
void down(int x)
{
int &p=a[x].son[],&q=a[x].son[];
if (a[x].hbe) {besingle(p,a[x].be); besingle(q,a[x].be); a[x].hbe=;}
if (a[x].rev) {revsingle(p); revsingle(q); a[x].rev=;}
}
int dsta[maxn],dtop;
void download(int x)
{
dtop=;
for (int i=x;i;i=a[i].fa) dsta[++dtop]=i;
while (dtop) down(dsta[dtop--]);
}
void rotate(int x)
{
const int y=a[x].fa,z=a[y].fa;
bool w=(x==a[y].son[]);
a[x].fa=z;
if (z) a[z].son[y==a[z].son[]]=x;
a[y].son[w^]=a[x].son[w];
if (a[x].son[w]) a[a[x].son[w]].fa=y;
a[x].son[w]=y;
a[y].fa=x;
up(y); up(z);
}
void splay(int x,int top)
{
if (!x) return;
download(x);
while (a[x].fa!=top)
{
const int y=a[x].fa,z=a[y].fa;
if (z!=top)
{
if ((x==a[y].son[])^(y==a[z].son[])) rotate(x);
else rotate(y);
}
rotate(x);
}
up(x);
if (!top) root=x; else up(top);
}
int find(int K)
{
// cout<<K<<endl;
int x=root,ans=;
if (K>a[root].size) ans=rbod;
else if (K==) ans=lbod;
else while (x)
{
// cout<<x<<' '<<K<<endl;
down(x);
if (x==lbod) x=a[x].son[];
else if (x==rbod) x=a[x].son[];
else if (a[a[x].son[]].size<K-) K-=a[x].size-a[a[x].son[]].size,x=a[x].son[];
else ans=x,x=a[x].son[];
}
if (ans) splay(ans,);
return ans;
}
void New(int &x) {x=sta[top--];}
void build(int &x,int L,int R)
{
if (L>R) {x=; return;}
New(x);
// cout<<x<<' '<<L<<' '<<R<<endl;
const int mid=(L+R)>>;
a[x].v=a[x].sum=a[x].Maxsum=num[mid]; a[x].size=; a[x].hbe=a[x].rev=;
if (num[mid]>=) a[x].lsum=a[x].rsum=num[mid];
else a[x].lsum=a[x].rsum=;
build(a[x].son[],L,mid-);
if (a[x].son[]) a[a[x].son[]].fa=x;
build(a[x].son[],mid+,R);
if (a[x].son[]) a[a[x].son[]].fa=x;
up(x);
}
void build(int &x,int n) {build(x,,n);}
void insert(int pos,int tot)
{
int x=find(pos),y=a[x].son[];
// cout<<x<<' '<<y<<endl;
while (a[y].son[]) down(y),y=a[y].son[];
splay(y,x);
build(a[y].son[],tot);
a[a[y].son[]].fa=y;
up(y); up(x);
}
void recycle(int x)
{
sta[++top]=x;
if (a[x].son[]) recycle(a[x].son[]);
if (a[x].son[]) recycle(a[x].son[]);
}
void Delete(int pos,int tot)
{
int y=find(pos+tot);
// test();
int x=find(pos-);
// test();
splay(y,x);
if (a[y].son[]) recycle(a[y].son[]);
a[y].son[]=; up(y); up(x);
}
void Be(int pos,int tot,int v)
{
int y=find(pos+tot),x=find(pos-);
splay(y,x);
besingle(a[y].son[],v);
up(y); up(x);
}
void Rev(int pos,int tot)
{
int y=find(pos+tot),x=find(pos-);
splay(y,x);
revsingle(a[y].son[]);
up(y); up(x);
}
int Sum(int pos,int tot)
{
// cout<<pos<<' '<<tot<<endl;
int y=find(pos+tot);
// test();
int x=find(pos-);
// test();
splay(y,x);
return a[a[y].son[]].sum;
}
int Maxsum() {return a[root].Maxsum;}
// void test(int x)
// {
// if (!x) return;
//// down(x);
// test(a[x].son[0]);
// cout<<x<<' '<<a[x].v<<" size"<<a[x].size<<" sum"<<a[x].sum<<" Maxsum"<<a[x].Maxsum
// <<" lsum"<<a[x].lsum<<" rsum"<<a[x].rsum<<" son0 "<<a[x].son[0]<<" son1 "<<a[x].son[1]
// <<" be"<<a[x].be<<" rev"<<a[x].rev<<endl;
// test(a[x].son[1]);
// }
// void test() {test(root);cout<<endl;}
}t; int qread()
{
char c;int s=,t=; while ((c=getchar())<'' || c>'') (c=='-' && (t=-));
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*t;
}
int main()
{
n=qread(); m=qread();
for (int i=;i<=n;i++) num[i]=qread();
t.insert(,n);
// t.test();
char c;
for (int i=,x,y,z;i<=m;i++)
{
// cout<<i<<"!!!"<<t.a[t.root].size<<' '<<t.a[0].size<<endl;
while ((c=getchar())<'A' || c>'Z');
if (c=='I')
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
x=qread(); y=qread();
for (int j=;j<=y;j++) num[j]=qread();
t.insert(x,y);
}
else if (c=='D')
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
x=qread(); y=qread();
t.Delete(x,y);
}
else if (c=='R')
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
x=qread(); y=qread();
t.Rev(x,y);
}
else if (c=='G')
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
x=qread(); y=qread();
printf("%d\n",t.Sum(x,y));
}
else
{
c=getchar(); c=getchar();
if (c=='K')
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
x=qread(); y=qread(); z=qread();
t.Be(x,y,z);
}
else
{
while (((c=getchar())>='A' && c<='Z') || c=='-');
printf("%d\n",t.Maxsum());
}
}
// t.up(t.lbod);
// t.test();
}
return ;
}

一练Splay之维修数列第一次的更多相关文章

  1. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  2. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  3. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  4. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  5. [BZOJ1500][NOI2005]维修数列 解题报告 Splay

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  6. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  7. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  8. splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)

    先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...

  9. [NOI2005] 维修数列

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 8397  Solved: 2530 Description In ...

随机推荐

  1. 转 SQL - 字符串中的转义字符

    一位同事在使用SQL处理一串字符时,出现一个意料之外的问题:这个字符串中包括字符‘&’.我们先看一下现象:     SQL> select * from v$version;     B ...

  2. IntelliJ IDEA导入JDK出现The selected directory is not a valid home for JDK问题的解决方法

    JDK版本与IDEA版本不兼容: JDK版本过高可能会造成这个问题,需与IDEA相兼容的JDK才行. 比如,用IDEA2016.3.8版本的,JDK用jdk-10.0.1_windows-x64_bi ...

  3. QScrollArea不能显示滚动条

    转载请注明出处:http://www.cnblogs.com/dachen408/p/7147141.html 问题:QScrollArea不能显示滚动条 解决方案:设置QScrollArea-> ...

  4. pthread Win32多线程编程的一些知识和感想

    研究遗传算法的一大诟病就是每次运行程序的结果并不是完全一样的,有时候能找到最优解有时候找不到最优解,这就是遗传算法的概率性导致的.那么怎么评价你的方法的好坏呐,这时候就要多次独立运行程序最后取结果的平 ...

  5. 8086汇编——Introduction(8086内部寄存器,段寄存器,存储器分段)

    8086汇编--Introduction 一.8086CPU的三种工作模式 实模式:只有低20位地址线起作用,仅能寻址第一个1MB的内存空间.MS DOS运行于该模式下. 保护模式:在该模式下,机器可 ...

  6. 手机信号强度单位:dBm 和 asu

    介绍 首先明确:dBm 和 asu 是两个独立的单位,它们的换算关系不唯一. 在 2G 网络下:dBm = -113+2*asu在 4G 网络下:dBm = -140+asu dBm 和 asu 都用 ...

  7. c语言 c++ 实现查看本地ip,外网ip, 本地主机名,查看http网址对应的ip

    /******************************************************************************* 作者 :邓中强 Email :1246 ...

  8. IIS启用32位应用程序兼容

    针对服务器出现html和jsp页面都可以应用,但唯独asp页面打不开的一种情况 win7的IIS运行在32状态下,原因是ASP程序必须在32位下才能使用ACCESS 设置办法: 打开IIS管理器,点应 ...

  9. oracle调用存储过程和函数返回结果集

    在程序开发中,常用到返回结果集的存储过程,这个在mysql和sql server 里比较好处理,直接返回查询结果就可以了,但在oracle里面 要 out 出去,就多了一个步骤,对于不熟悉的兄弟们还得 ...

  10. UIWebView中javascript与Objective-C交互、获取摄像头

    UIWebView是iOS开发中常用的一个视图控件,多数情况下,它被用来显示HTML格式的内容. 支持的文档格式 除了HTML以外,UIWebView还支持iWork, Office等文档格式: Ex ...