序言

此日志分为四部分。

00:00是开始打代码的时间。

最开始打完代码(没有debug)大约用了两小时。

part1-20210323

02:30

生成新节点时,没有给随机权值。

02:41

upd中,sum更新时没有先清空,没有加上右儿子的sum。

02:46

操作12没问题

操作3会RE+WA

5 100000
0 0 0 1 1
3 1 5

change1中第7行,merge中顺序反了。

change1中第11行,分裂出的子树错误(\(z\rightarrow y\))。

03:01

split1中if(k>l[i])应为if(k>=l[i])

分裂左/右子树反了。

03:07

assign中,\(l\not=1\&\&r=n\)中\(lv[y]=x\)的case中,没有拓展同色区间。root=merge(x,node(l,n,v));改为root=merge(x,node(ll[y],n,v));

1和l看错了root=merge(root,node(1,rr[y],v));应为root=merge(root,node(l,rr[y],v));

x和1搞错了if(lv[y]!=x)应为if(lv[y]!=v)

03:10~11:40

睡觉

11:57

change1中,修改y树的根时work(y,1,flag==1?1:-1);应为work(y,0,flag?1:-1);

12:02

dfs中始终只会spread rootspread(root);改为spread(x);

12:33

spread中只要有一种标记没有打,则就不会下传标记if(!lazy[x][0]||!lazy[x][1]) return;应为if(!lazy[x][0]&&!lazy[x][1]) return;

过样例,WA+MLE+RE

12:45

hack:

5 10000
1 0 0 0 0
4 1 5

树的结构错误的变成了

1 1 1
3 5 0

操作4错误

12:55

打模拟赛

14:22

上面的错误是debug错了,输出树的结构没有spread。

15:32

忘记强制在线了,WA-ALL(说明只差一点点了!)

15:32

写了对拍(无加密)

10 100
1 1 0 1 0 0 0 1 0 0
3 3 6
5 1 4
5 4 7
7 7 8
5 5 6
3 10 10
4 6 9
3 8 9
3 5 10
7 2 9
5 6 9
6 3 10
4 1 1
1 7 7
4 4 8
2 4 7
5 5 9
1 9 9
7 1 4
5 3 4
2 2 8
2 9 10
7 8 10
2 2 7
7 3 9

我输出

1
2
2
3
7

std

1
5
4
3
7

为什么修改无效?

16:30

午餐

17:20

午休

18:12

下午好

下午没有做什么,所以暂停了计时。

18:56

晚上好。加油吧,\(Vanilla\_chan\)!

19:25

重写了upd,assign函数

/**************************************************************
* Problem: 5066
* Author: Vanilla_chan
* Date: 20210323
* E-Mail: Vanilla_chan@outlook.com
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std; namespace oi
{
inline bool isdigit(const char& ch)
{
return ch<='9'&&ch>='0';
}
inline bool isalnum(const char& ch)
{
return (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9');
}
struct istream
{
char ch;
bool fu;
template<class T>inline istream& operator>>(T& d)
{
fu=d=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=1,ch=getchar();
d=ch-'0';ch=getchar();
while(isdigit(ch))
d=(d<<3)+(d<<1)+(ch^'0'),ch=getchar();
if(fu) d=-d;
return *this;
}
inline istream& operator>>(string& str)
{
str.clear();
for(;!isdigit(ch);ch=getchar());
while(isalnum(ch))
str+=ch,ch=getchar();
return *this;
}
}cin;
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do { G[++g]=x%10;x/=10; } while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
};
using namespace oi; #define N 6000010 int n,m;
int a[N];
int root;
int key[N];
int l[N],r[N];//平衡树上一个点所代表的一段区间[l,r]
int ll[N],rr[N];//平衡树上一个点的子树代表的一段区间[ll,rr]
bool val[N];//当前点代表区间的值0/1
int ls[N],rs[N];//左右儿子
int cnt[N][2];//以当前点为根的子树内的0/1段数量
int mn[N][2];//以当前点为根的子树内,最短的0/1段的长度
int sum[N];//当前点的子树和
bool lv[N],rv[N];//当前点的子树的边界位置的值
int lazy[N][2];
int tot;
void upd(int x)
{
if(ls[x]) ll[x]=ll[ls[x]];
else ll[x]=l[x];
if(rs[x]) rr[x]=rr[rs[x]];
else rr[x]=r[x];
cnt[x][val[x]]=1;
cnt[x][!val[x]]=0;
mn[x][val[x]]=r-l+1;
mn[x][!val[x]]=n+1;
if(val[x]) sum[x]=r[x]-l[x]+1;
else sum[x]=0;
if(ls[x]) lv[x]=lv[ls[x]];
else lv[x]=val[x];
if(rs[x]) rv[x]=rv[rs[x]];
else rv[x]=val[x];
if(ls[x])
{
cnt[x][0]+=cnt[ls[x]][0];
cnt[x][1]+=cnt[ls[x]][1];
mn[x][0]=min(mn[x][0],mn[ls[x]][0]);
mn[x][1]=min(mn[x][1],mn[ls[x]][1]);
sum[x]+=sum[ls[x]];
}
if(rs[x])
{
cnt[x][0]+=cnt[rs[x]][0];
cnt[x][1]+=cnt[rs[x]][1];
mn[x][0]=min(mn[x][0],mn[rs[x]][0]);
mn[x][1]=min(mn[x][1],mn[rs[x]][1]);
sum[x]+=sum[rs[x]];
}
}
int node(int L,int R,bool vv)
{
tot++;
l[tot]=L;
r[tot]=R;
val[tot]=vv;
key[tot]=rand();
ls[tot]=rs[tot]=0;
lazy[tot][0]=lazy[tot][1]=0;
upd(tot);
return tot;
}
void work(int x,bool flag,int k)
{
//if(!x||!k) return;
lazy[x][flag]+=k;
if(flag)
{
if(val[x]) r[x]+=k;
else l[x]+=k;
}
else
{
if(val[x]) l[x]-=k;
else r[x]-=k;
}
mn[x][0]-=k;
mn[x][1]+=k;
sum[x]+=k*cnt[x][1];
}
void spread(int x)
{
//if(!lazy[x][0]&&!lazy[x][1]) return;
if(ls[x]) work(ls[x],0,lazy[x][0]),work(ls[x],1,lazy[x][1]);
if(rs[x]) work(rs[x],0,lazy[x][0]),work(rs[x],1,lazy[x][1]);
lazy[x][0]=lazy[x][1]=0;
}
int merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
if(key[x]>key[y])
{
spread(x);
rs[x]=merge(rs[x],y);
upd(x);
return x;
}
else
{
spread(y);
ls[y]=merge(x,ls[y]);
upd(y);
return y;
}
}
void split1(int i,int k,int& x,int& y)
{
if(!i)
{
x=y=0;
return;
}
spread(i);
if(k>=l[i])
{
split1(rs[i],k,rs[i],y);
x=i;
}
else
{
split1(ls[i],k,x,ls[i]);
y=i;
}
upd(i);
}
void split2(int i,int k,int& x,int& y)
{
if(!i)
{
x=y=0;
return;
}
spread(i);
if(k<=r[i])
{
split2(ls[i],k,x,ls[i]);
y=i;
}
else
{
split2(rs[i],k,rs[i],y);
x=i;
}
upd(i);
}
int ask(int l,int r)
{
int x,y,z;
split2(root,l,x,y);//可以切多但是不能切少
split1(y,r,y,z);//所以这里切最左侧时,应是小于当前块的右边界
int ans=sum[y];//这样即使有可能让l在最左边的一块内部,但是下面会将多余的减去。反之同理
if(lv[y]) ans-=l-ll[y];
if(rv[y]) ans-=rr[y]-r;
root=merge(x,merge(y,z));
return ans;
}
void assign(int l,int r,bool v)
{
int x,y,z;
if(l==1)
{
if(r==n)
{
root=node(l,r,v);
return;
}
else
{
split1(root,r+1,x,y);
//if(rv[x]!=v) root=merge(merge(node(1,r,v),node(r+1,rr[x],!v)),y);
//else root=merge(node(1,rr[x],v),y);
if(rv[x]!=v)
{
root=node(1,r,v);
root=merge(root,node(r+1,rr[x],!v));
}
else
{
root=node(1,rr[x],v);
}
root=merge(root,y);
}
}
else
{
if(r==n)
{
split2(root,l-1,x,y);
//if(lv[y]!=v) root=merge(x,merge(node(ll[y],l-1,!v),node(l,n,v)));
//else root=merge(x,node(ll[y],n,v));
root=x;
if(lv[y]!=v)
{
root=merge(root,node(ll[y],l-1,!v));
root=merge(root,node(l,n,v));
}
else
{
root=merge(root,node(ll[y],n,v));
}
}
else
{
split2(root,l-1,x,y);
split1(y,r+1,y,z);
root=x;
/*
if(lv[y]!=v)
{
root=merge(root,node(ll[y],l-1,!v));
if(rv[y]!=v)
{
root=merge(root,node(l,r,v));
root=merge(root,node(r+1,rr[y],!v));
}
else
{
root=merge(root,node(l,rr[y],v));
}
}
else
{
if(rv[y]!=v)
{
root=merge(root,node(ll[y],r,v));
root=merge(root,node(r+1,rr[y],!v));
}
else
{
root=merge(root,node(ll[y],rr[y],v));
}
}
root=merge(root,z);
*/
if(lv[y]!=v)
{
root=merge(root,node(ll[y],l-1,!v));
if(rv[y]!=v)
{
root=merge(root,node(l,r,v));
root=merge(root,node(r+1,rr[y],!v));
}
else
{
root=merge(root,node(l,rr[y],v));
}
}
else
{
if(rv[y]!=v)
{
root=merge(root,node(ll[y],r,v));
root=merge(root,node(r+1,rr[y],!v));
}
else
{
root=merge(root,node(ll[y],rr[y],v));
}
root=merge(root,z);
} }
}
}
void change1(int l,int r,bool flag)//向左传递flag
{
int x,y,z,t;
split1(root,l-1,x,y);
split1(y,r,y,z);
if(y&&lv[y])
{
split2(x,ll[y]-1,x,t);
y=merge(t,y);
}
if(y&&!rv[y])
{
split2(y,rr[x],y,t);
z=merge(t,z);
}
if(y)
{
work(y,0,flag?1:-1);
}
root=merge(x,merge(y,z));//FHQ-Treap常规操作
}
void change2(int l,int r,bool flag)
{
int x,y,z,t;
split2(root,r+1,y,z);
split2(y,l,x,y);
if(y&&rv[y])
{
split1(z,rr[y]+1,t,z);
y=merge(y,t);
}
if(y&&!lv[y])
{
split1(y,ll[y],t,y);
x=merge(x,t);
}
if(y)
{
work(y,1,flag?1:-1);
}
root=merge(x,merge(y,z));
}
int dfs(int x)
{
//debug cout<<"x="<<x<<endl;
spread(x);
if(l[x]==r[x]+1) return l[x];
else if(ls[x]&&(!mn[ls[x]][0]||!mn[ls[x]][1]))
{
return dfs(ls[x]);
}
else return dfs(rs[x]);
}
void del()
{
int t=dfs(root);
int x,y,z;
split2(root,t-1,x,y);
split1(y,t,y,z);
root=merge(x,merge(node(ll[y],rr[y],r[y]+1==l[y]?!val[y]:val[y]),z));
}
void init()
{
int res=1;
for(int i=2;i<=n;i++)
{
if(a[i]!=a[i-1])
{
root=merge(root,node(res,i-1,a[res]));
res=i;
}
}
root=merge(root,node(res,n,a[res]));
}
void out(int x)
{
spread(x);
if(ls[x]) out(ls[x]);
cout<<"id="<<x<<" "<<l[x]<<" "<<r[x]<<" "<<val[x]<<endl;
if(rs[x]) out(rs[x]);
}
int op,x,y;
int lastans; int main()
{
freopen("5066.in","r",stdin);
//freopen(".out","w",stdout);
oi::cin>>n>>m;
srand(20050228);
for(int i=1;i<=n;i++) oi::cin>>a[i];
init();
while(m--)
{
op=read();
x=read();
y=read();
//x^=lastans;
//y^=lastans;
if(op==1)
{
assign(x,y,0);
}
else if(op==2)
{
assign(x,y,1);
}
else if(op==3)
{
change1(x+1,y,1);
}
else if(op==4)
{
change2(x,y-1,1);
}
else if(op==5)
{
change2(x,y-1,0);
}
else if(op==6)
{
change1(x+1,y,0);
}
else
{
write(lastans=ask(x,y));
}
//out(root);
while(!mn[root][0]||!mn[root][1]) del();
debug
out(root);
}
return 0;
}

显然这份代码不能过。能过就折寿了。

part2-20210327~20210328

在家与学校之间的地铁上debug。

upd函数中,r[x]-l[x]+1写成r-l+1

重构代码,用指针全部重写。

\(0pts\).

part3-20210329

整个下午都在调指针。

过了自己的样例……还是\(0pts\).

又造出了一组hack数据!

debug……80pts

数组开小了,\(3\times 10^6\)。

还是80pts……

卡常,卡常,跑完操,没吃晚饭。

找lxl小姐姐请求放大时限(然后把最后一组数据调成了8s)还是过不去。

果然,越可爱就会越毒瘤吗……

part4-20210330

进入了漫长的卡常期……

delete废弃的指针(反正不会MLE)

把所有的==!=都改成了^

while(!root->mn[0]||!root->mn[1]) update();改写到3|4|5|6内部去,减少四个if

将随机数改写成了s*=13并\(\text{unsigned int}\)自然溢出。

spread等函数全部inline,并判断有lazy时再进入函数操作(if放到函数外面减少调用次数)。

将快读变为传址。

删除无关头文件。

split1/2中的k既不会修改也不会冲突,就去掉这个参数改为全局变量吧。

可以过\(\#27\)了!

将随机数改写成s=(s<<1)+s.等价于s*=3

ans变为全局变量,同时就可以不用lastans了。

对于update中的\(x\)同理。

我傻了,随机数怎么可以写成s*=3?那样对于一段内的key不久全是单调的了嘛!

换成s*=19260817

可以过\(\#31\)了!\(90pts\)

ask,assign,change1.change2函数中的*x,*y,*z,*t设置成全局的。

将有\(bool\)变量参数的函数全部分程两个,比如\(change1\)写成\(change10\)和\(change11\),\(change2\)写成\(change20\)和\(change21\),\(assign\)写成\(assign0\)和\(assign1\),\(work\)写成\(work0\)和\(work1\)。

关于随机数,试了s=s*3^3在\(\text{unsigned short int}\)下虽然跑的很满很快,但是实际效果不如s*=19260817在\(\text{unsigned int}\)。于是我就换成了s*=1000000009在\(\text{long long}\)下的自然溢出。

考虑到读取\(3\times 10^6\)个\(\text{bool}\)变量用读取\(\text{int}\)的快读还是可圈可点的。所以写了readbool

inline void readbool(bool &xx)
{
ch=getchar();
while(!isdigit(ch)) ch=getchar();
xx=ch-'0';
}

\(\textbf{2021-03-31 08:00:25 thus,AC.}\)


第129发过了。

洛谷 P5066 [Ynoi2014] 人人本着正义之名debug-log的更多相关文章

  1. 洛谷 P4062 - [Code+#1]Yazid 的新生舞会 的线性做法

    洛谷题面传送门 一个线性做法. \(n\log n\) 解法可以戳这里查看 首先回顾一下 \(n\log n\) 解法的过程:我们对于每一个数 \(x\),考察其出现位置,设为 \(t_1,t_2,t ...

  2. C++ 洛谷 2014 选课 from_树形DP

    洛谷 2014 选课 没学树形DP的,看一下. 首先要学会多叉树转二叉树. 树有很多种,二叉树是一种人人喜欢的数据结构,简单而且规则.但一般来说,树形动规的题目很少出现二叉树,因此将多叉树转成二叉树就 ...

  3. 「树形DP」洛谷P2607 [ZJOI2008]骑士

    P2607 [ZJOI2008]骑士 题面: 题目描述 Z 国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的 ...

  4. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  5. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  6. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  7. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

  8. 洛谷P1710 地铁涨价

    P1710 地铁涨价 51通过 339提交 题目提供者洛谷OnlineJudge 标签O2优化云端评测2 难度提高+/省选- 提交  讨论  题解 最新讨论 求教:为什么只有40分 数组大小一定要开够 ...

  9. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

  10. 洛谷P1538迎春舞会之数字舞蹈

    题目背景 HNSDFZ的同学们为了庆祝春节,准备排练一场舞会. 题目描述 在越来越讲究合作的时代,人们注意的更多的不是个人物的舞姿,而是集体的排列. 为了配合每年的倒计时,同学们决定排出——“数字舞蹈 ...

随机推荐

  1. 【Python】转载一个python 爬虫的帖子

    原帖地址 原帖标题:爬取图网的4K图片自动保存本地 https://www.52pojie.cn/thread-1809600-1-1.html (出处: 吾爱破解论坛) python 代码 impo ...

  2. sap 管理--企业解决方案 -设备管理

    1.什么是sap 管理 2.设备管理管的是什么 3.设备的几种状态 4.设备bom(物料清单) 5.测量点计数器 1.什么是sap 管理 System Applications and Product ...

  3. 错误修正记录:对应的VMware Tools脚本未能成功运行

    起因 装了台式机,想把笔记本里的vmware虚拟机迁移过来:复制过来后开机就出现这种情况,点开机.挂起.关机等操作会报错,然后无法挂起(再点一次就行) 或者使用下方的选项,而非上方包装过的功能,似乎也 ...

  4. [tldr]github仓库添加release

    作为一个开源项目开发者,并且把自己的代码仓库托管到了github上面,所以,可以在github上提供自己的程序的release 这通常是通过二进制可执行文件的方式提供 新建草稿 点击create a ...

  5. 前缀函数和 KMP "跳步骤"模式匹配

    在一篇由字符构成的长文中查找另一个短字符串出现的位置,这可以算是编程领域最最常见的问题(比如按下 Ctrl + F 就可以打开你浏览器的查找功能).这个问题叫做字符串的模式匹配,我们把被查找的关键词叫 ...

  6. StarRocks 升级注意事项

    前段时间升级了生产环境的 StarRocks,从 3.3.3 升级到了 3.3.9,期间还是踩了不少坑所以在这里记录下. 因为我们的集群使用的是存算分离的版本,也是使用官方提供的 operator 部 ...

  7. Windows下Dll在Unity中使用的一般方式

    Windows下Dll在Unity中使用的一般方式 Unity中虽然已经有广泛的库和插件,但是相较于C++的库生态而言,还是有一定的差距:因此本篇博文记录Windows下将C++函数打包成动态链接库在 ...

  8. CSS那些事读书笔记-2

    背景 作为一个后端开发,曾经尝试过学习前端,但是总觉不得要领,照猫画虎,而公司里又有专业的前端开发,工作中几乎接触不到实际的前端任务,所以前端的技能田野一直是一片荒芜.但是笔者深知前端的技能对找工作和 ...

  9. 阅读IDEA生成的equals方法--java进阶day05

    1.IDEA生成的equals方法 虽然我们之前写了equals方法,但IDEA中可以快速生成equals方法,因此,我们要能看懂IDEA生成的equals方法 1.if(this==o) 2.if( ...

  10. CSS文本超出省略

    语法: text-overflow:clip|ellipsis|"任意字符" <!DOCTYPE html> <html> <head> < ...