【icpc2019网络赛南昌站】Yukino With Subinterval
傻b错误调一天系列
原题:

大意:给你一个数列a,字词两种操作:
1.把c[l]改成r
2.询问在区间[l,r]中,有多少个极大子区间满足子区间里的数全部一样,且在[x,y]范围内
(对于满足条件的区间A,若不存在满足条件的区间B使得A包含于B,则称A为极大子区间)
序列问题,要求复杂度O(nlogn),联想cdq分治
值域可以容斥拆成[1,l-1]和[1,r]两个询问,即把询问转化为区间中数小于等于x的数有多少个
可以把初始数列看成0,然后用修改操作代替初始数列
那么现在就存在偏序:若修改A的时间小于询问B,且A的值小于B的值,则A可以给B提供贡献
对于计算贡献,我们建一个线段树,字词单点修改,并查询有多少个不同的非0极大子区间,这个比较好写
初始按时间排序,然后按值域分治
然后这题就做完了马
反例:
6 3
1 1 4 5 1 4
2 1 6 2 5
1 6 1
2 1 6 2 5
上面的做法会输出3 3,正确答案却是3 2
考试的时候我写这个做法然后深度自闭
出错的原因是因为我们按值域分治,那么当第6个数(被视为操作1 6 4)和第三个操作(2 1 6 2 5)分到一个分治区间时,因为操作2(1 6 1)被分到左边的分治区间了,所以不会把代表第6个数的操作覆盖掉,这时第6个数就给第3个操作产生了贡献(尽管第三个操作进行时它已经被覆盖掉了)
更换提供贡献的顺序是不行的,这是个死循环,不管是用前序、中序或后序cdq分治都无法解决,根本原因是操作2(1 6 1)实际上给操作3(2 1 6 2 5)一个负贡献(它把一个本来合法的区间变得不合法),却因为值域没有达到操作3的范围([2,5])而被忽略了
这个负贡献在分治过程中无法统计(至少我没找到方法)
正确做法是
只考虑一个区间中的左端点那个数,新建一个数组b,对于每个b[i],若a[i]==a[i-1]则b[i]为0否则为a[i]
问题就转化为求区间[l+1,r]中有多少个数,最后单独特判a[l]是否在区间[x,y]内
这个就是经典cdq分治问题,由于数的值域为[1,n],所以用权值线段树(树状数组)可以方便地统计贡献
这种做法和上一种的根本区别在于一个修改操作是覆盖,而另一个是增添和删除,在分治中第二种统计贡献比第一种简单直接很多
然后我就迎来了这题第二次自闭,在晚上10:30写出正确代码后找bug到11:30,直至次日下午5:00才发现问题
只因为一句话的位置:

这是对操作1的处理,注释代码为原位置
如果把d[i]赋值写在后边,就会导致当r==c[l]时,d[i]={0,0,0,0,0,0,0},而我在判断是否应该输出的时候是靠d[i].mk是否为1来判断的
这就导致当r==c[l]发生时,会有修改操作被当成查询操作多输出一个数,自然会WA
这个bug我花了这么长时间没找出来,一个很重要的原因时总在原地打转,算法基本框架检查过很多遍没有问题了,就应该去思考一些细节,尤其是看起来很奇怪很特殊的部分
我倒是看了细节,但是偏偏没有注意到这么奇怪而特殊的一个特判
这个故事也告诉我们有时候睡一觉休息一下bug就自己出来了,不能盲目死磕
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
struct nds{int mk,x,y,z,id,ans;}a[]; int atp=;
int n,m;
int b[],c[];
nds q[];
int v[];
int ans[];
nds d[];
inline int lbt(int x){ return x&-x;}
void mdf(int x,int y){ for(;x<=n;x+=lbt(x)) v[x]+=y;}
int qry(int x){ int bwl=; for(;x;x-=lbt(x)) bwl+=v[x]; return bwl;}
void cdq(int x,int y,int l,int r){
if(x>=y) return ;
if(l>r) return ;
if(l==r){
for(int i=x;i<=y;++i){
if(!a[i].mk) mdf(a[i].y,a[i].z);
else a[i].ans+=qry(a[i].z)-qry(a[i].y-);
}
for(int i=x;i<=y;++i)if(!a[i].mk) mdf(a[i].y,-a[i].z);
return ;
}
int md=(l+r)>>;
int cnt1=;
for(int i=x;i<=y;++i){
if(a[i].x<=md) ++cnt1;
if(!a[i].mk && a[i].x<=md) mdf(a[i].y,a[i].z);
if(a[i].mk && a[i].x>md) a[i].ans+=qry(a[i].z)-qry(a[i].y-);
}
for(int i=x;i<=y;++i)if(!a[i].mk && a[i].x<=md)
mdf(a[i].y,-a[i].z);
int hd1=x,hd2=x+cnt1;
for(int i=x;i<=y;++i){
if(a[i].x<=md) q[hd1++]=a[i];
else q[hd2++]=a[i];
}
for(int i=x;i<=y;++i) a[i]=q[i];
cdq(x,hd1-,l,md),cdq(hd1,y,md+,r);
}
void prvs(){
atp=;
for(int i=;i<=m;++i) ans[i]=;
}
int main(){
//freopen("ddd.in","r",stdin);
cin>>n>>m;
prvs();
for(int i=;i<=n;++i) c[i]=rd();
c[]=,c[n+]=;
for(int i=;i<=n;++i){
if(c[i]!=c[i-]) a[++atp]=(nds){,i,c[i],,-,};
b[i]=c[i];
}
int mk,l,r,ql,qr;
for(int i=;i<=m;++i){
mk=rd();
if(mk==){
l=rd(),r=rd();
d[i]=(nds){mk,l,r,,,i};
if(r==c[l]) continue;
if(c[l]!=c[l-]) a[++atp]=(nds){,l,c[l],-,i,};
if(r!=c[l-]) a[++atp]=(nds){,l,r,,i,};
if(l<n){
if(r==c[l+]) a[++atp]=(nds){,l+,c[l+],-,i,};
if(c[l]==c[l+]) a[++atp]=(nds){,l+,c[l+],,i,};
}
c[l]=r;
//d[i]=(nds){mk,l,r,0,0,i}; Attention!!!
}
else{
l=rd(),r=rd(),ql=rd(),qr=rd();
a[++atp]=(nds){,r,ql,qr,i,};
a[++atp]=(nds){-,l,ql,qr,i,};
d[i]=(nds){mk,l,r,ql,qr,i};
}
}
cdq(,atp,,n);
for(int i=;i<=atp;++i)if(a[i].mk) ans[a[i].id]+=a[i].mk*a[i].ans;
for(int i=;i<=m;++i){
if(d[i].mk==) b[d[i].x]=d[i].y;
else printf("%d\n",ans[i]+(b[d[i].x]>=d[i].z && b[d[i].x]<=d[i].id));
}
return ;
}
【icpc2019网络赛南昌站】Yukino With Subinterval的更多相关文章
- ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval
ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询 ...
- 2019南昌网络赛 I. Yukino With Subinterval 树状数组套线段树
I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...
- 2018ICPC网络赛(焦作站)E题题解
一.题目链接 二.题意 给定一棵树,有四种操作: $1\ u\ v\ x$:把节点$u$到$v$路径上的所有点的权值乘以$x$: $2\ u\ v\ x$:把节点$u$到$v$路径上的所有点的权值加上 ...
- 2018ICPC网络赛(焦作站)K题题解
一.题目链接 https://nanti.jisuanke.com/t/31720 二.题意 给$N$种船只,第$i$种船的载重量是$V_i$,数量是$2^{C_i}-1$.接下来有$Q$次询问,每次 ...
- 2018ICPC网络赛(徐州站)A题题解
一.题目链接 https://nanti.jisuanke.com/t/31453 二.题意 给定$N$个位置,$2^k$种颜色,让你去涂色,条件是相邻的两种颜色类型异或值的二进制表示不全为$1$(以 ...
- 2019南昌网络赛I:Yukino With Subinterval(CDQ) (树状数组套主席树)
题意:询问区间有多少个连续的段,而且这段的颜色在[L,R]才算贡献,每段贡献是1. 有单点修改和区间查询. 思路:46min交了第一发树套树,T了. 稍加优化多交几次就过了. 不难想到,除了L这个点, ...
- 2019 ICPC 南昌网络赛I:Yukino With Subinterval(CDQ分治)
Yukino With Subinterval Yukino has an array a_1, a_2 \cdots a_na1,a2⋯*a**n*. As a tsundere girl, Yuk ...
- 南昌邀请赛网络赛 D.Match Stick Game(dp)
南昌邀请赛网络赛 D.Match Stick Game 题目传送门 题目就会给你一个长度为n的字符串,其中\(1<n<100\).这个字符串是一个表达式,只有加减运算符,然后输入的每一个字 ...
- dp--2019南昌网络赛B-Match Stick Game
dp--2019南昌网络赛B-Match Stick Game Xiao Ming recently indulges in match stick game and he thinks he is ...
随机推荐
- VS2019 安装并破解 DevExpress 19.2 插件
0.写在最前 本人vs版本为: 1.下载DevExpress 最新版本插件程序 官网下载试用30天地址: https://www.devexpress.com/products/net/con ...
- Guava源码阅读-base-Strings
package com.google.common.base; 今天阅读的是Srings类,这在程序中经常使用. 比如判断字符串是否为空,我们在之前用jdk方法判断是会用下面这个判断语句. if( i ...
- Docker 运行hello world
Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序. 输出Hello world docker run ubuntu:15.10 /bin/echo ...
- mysql语句(一)
--建表CREATE TABLE IF NOT EXISTS `runoob_tbl`( `runoob_id` INT UNSIGNED AUTO_INCREMENT, `runoob_title` ...
- css小记:hover 鼠标滑过让该元素的子元素或者其他元素改变样式
<!DOCTYPE><head><meta http-equiv="Content-Type" content="text/html; ch ...
- tee、vi/vim命令
一.tee:多重定向 语法: tee [OPTION] ... [FILE] ... 参数: 将标准输入复制到每个FILE,也复制到标准输出. -a,--append ...
- mysql在B-Tree上创建伪哈希索引
构建哈希的过程 select过程 长字符串下,构建索引可通过自定义哈希作为索引,本人通过实验,在3百多个数据记录的下,性能效果很明显,完全不是一个等级.以下为索引前后几种情况对比 无索引的url:直接 ...
- (转)关于Android中为什么主线程不会因为Looper.loop()里的死循环卡死?引发的思考,事实可能不是一个 epoll 那么 简单。
( 转载请务必标明出处:http://www.cnblogs.com/linguanh/, 本文出自:[林冠宏(指尖下的幽灵)的博客]) 前序 本文将会把一下三个问题阐述清楚以及一个网上的普遍观点的补 ...
- ubuntu下npm全局安装包报错的解决方案
大概就是 npm WARN registry Unexpected warning for https://registry.npmjs.org/: Miscellaneous Warning ERR ...
- C# HttpWebRequest请求远程地址获取返回消息
HttpWebRequest请求远程地址获取返回消息 /// <summary> /// 请求远程Api获取响应返回字符串 /// </summary> /// <par ...