6.6 省选模拟赛 线段 二维数点问题 树套树 CDQ分治
LINK:线段
还是太菜了 没看出这道题真正的模型 我真是一个典型的没脑子选手。
考虑如何查询答案。
每次在一个线段x的状态被更改后 可以发现有影响的是 和x相连那段极长连续1子段。
设这个子段左端点为l 右端点为r 那么容易发现 左端点为 l~x 右端点为 x~r 这些询问的贡献将会变化。
将这个变化映射到二维平面上 那么每次询问就是询问某个点的类似的权值。
考虑一条线段在 T1时刻是联通的 T2时刻不连通了 那么对答案的贡献为T2-T1.
至此每次修改都可以看成给二维平面上某个区域加上一个值。
那么对于询问 考虑当前点是否是联通的 如果不连通那就是当前点权 如果联通就是i+当前点权 因为只有不连通的时候贡献才会产生 此时强制性让其不连通即可。
那么就是一个二维数点问题。经典模型是CDQ分治解决。
当然一个比较无脑的实现是 线段树套线段树 或者 树状数组套线段树。
当然内层线段树都需要是 动态开点+标记永久化。下传懒标记对空间开销过大。
值得一提的是查最远和左右端点的问题 如果采用线段树上二分感觉比往常的要繁琐很多 所以采用的是树状数组+二分 当然也可以二分+set等等。
这里用的是CDQ分治.
const int MAXN=300010;
int n,Q,cnt;
char a[MAXN];
int c[MAXN],ans[MAXN];ll s[MAXN];
struct wy{int x,y,id;int op;}t[MAXN*4],tmp[MAXN*4];
inline int ask(int x){int cnt=0;while(x)cnt+=c[x],x-=x&-x;return cnt;}
inline void add(int x,int y){while(x<=n)c[x]+=y,x+=x&-x;}
inline ll ask1(int x){ll cnt=0;while(x)cnt+=s[x],x-=x&-x;return cnt;}
inline void add1(int x,int y){while(x<=n)s[x]+=y,x+=x&(-x);}
inline int check(int l,int r){return ask(r)-ask(l-1)>=r-l+1;}
inline int askr(int x)
{
if(x==n)return x;
if(!check(x+1,x+1))return x;
int l=x+1,r=n;
while(l+1<r)
{
int mid=(l+r)>>1;
if(check(x+1,mid))l=mid;
else r=mid;
}
if(check(x+1,r))return r;
return l;
}
inline int askl(int x)
{
if(x==1)return x;
if(!check(x-1,x-1))return x;
int l=1,r=x-1;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid,x-1))r=mid;
else l=mid+1;
}
return r;
}
inline void CDQ(int l,int r)//第一维时间 第二维横坐标 第三维纵坐标.
{
if(l==r)return;
int mid=(l+r)>>1;
CDQ(l,mid);
CDQ(mid+1,r);//两边都按照横坐标排好序.
int i=l,j=mid+1,mark=r;
rep(l,r,k)
{
if(i<=mid&&j<=r)
{
if(t[i].x<=t[j].x)
{
if(op(i))add1(t[i].y,op(i));
tmp[k]=t[i];++i;
}
else
{
if(!op(j))ans[id(j)]+=ask1(t[j].y);
tmp[k]=t[j];++j;
}
}
else
{
mark=min(mark,i-1);
if(i<=mid)tmp[k]=t[i],++i;
else
{
if(!op(j))ans[id(j)]+=ask1(t[j].y);
tmp[k]=t[j];++j;mark=mid;
}
}
}
rep(l,mark,i)if(op(i))add1(t[i].y,-op(i));
rep(l,r,k)t[k]=tmp[k];//归并结束.
}
int main()
{
freopen("1.in","r",stdin);
//freopen("segment.out","w",stdout);
gt(n);gt(Q);gc(a);
rep(1,n,i)
{
c[i]+=a[i]-'0';
if((i+(i&-i))<=n)c[i+(i&-i)]+=c[i];
}
rep(1,Q,i)
{
gc(a);ans[i]=-1;
if(a[1]=='q')
{
int l,r;gt(l),gt(r);--r;
int wr=askr(l-1);ans[i]=0;
if(wr>=r)ans[i]+=i;//此时是联通的 需要强制断开.
t[++cnt]=(wy){l,r,i,0};//查询(1,1) 到 (l,r)的矩形和.
}
else
{
int x;gt(x);
int wl=askl(x);
int wr=askr(x);
int ww=check(x,x);
if(ww)//当前是联通的.
{
t[++cnt]=(wy){wl,x,i,i};
if(wr+1<=n)t[++cnt]=(wy){wl,wr+1,i,-i};
if(x+1<=n)t[++cnt]=(wy){x+1,x,i,-i};
if(wr+1<=n)t[++cnt]=(wy){x+1,wr+1,i,i};
add(x,-1);
}
else
{
t[++cnt]=(wy){wl,x,i,-i};
if(wr+1<=n)t[++cnt]=(wy){wl,wr+1,i,i};
if(x+1<=n)t[++cnt]=(wy){x+1,x,i,i};
if(wr+1<=n)t[++cnt]=(wy){x+1,wr+1,i,-i};
add(x,1);
}
}
}
CDQ(1,cnt);
rep(1,Q,i)if(ans[i]!=-1)put(ans[i]);
return 0;
}
6.6 省选模拟赛 线段 二维数点问题 树套树 CDQ分治的更多相关文章
- [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)
题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...
- loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分
$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
- 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)
[BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...
- 【线段树 扫描线 二维数点】loj#6276. 果树
路径计数转成二维数点很妙啊 题目描述 NiroBC 姐姐是个活泼的少女,她十分喜欢爬树,而她家门口正好有一棵果树,正好满足了她爬树的需求. 这颗果树有 $N$ 个节点,标号 $1 \ldots N$ ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay
P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...
随机推荐
- MSIL入门(一)C#代码与IL代码对比
基础概念 Microsoft中间语言(MSIL),也成为通用中间语言(CIL),是一组与平台无关的指令,由特定于语言的编译器从源代码生成.MSIL是独立于平台的,因此,他可以在任何公共语言基础架构支持 ...
- 如何嵌套一个网页html到另一个html中
在常规网页开发中(单页应用除外哈),经常会遇到把一些通用内容的页面集中到一个页面中,需要使用这些页面只需要包含引入即可,这样有利于维护和修改,当通用页面修改时只需更改一个文件就可以了,不需要每个文件单 ...
- 结合实际需求,在webapi内利用WebSocket建立单向的消息推送平台,让A页面和服务端建立WebSocket连接,让其他页面可以及时给A页面推送消息
1.需求示意图 2.需求描述 原本是为了给做unity3d客户端开发的同事提供不定时的消息推送,比如商城购买道具后服务端将道具信息推送给客户端. 本篇文章简化理解,用“相关部门开展活动,向全市人民征集 ...
- URL编码与二次encodeURI
转自:http://foryougeljh.iteye.com/blog/1456706 一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号.比如,世界上有英文字母的网 ...
- Cypress系列(13)- 详细介绍 Cypress Test Runner
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前言 Test Runner 也叫运行器 ...
- Kafka入门(1):概述
摘要 在本文中,我将从为什么需要消息队列开始讲起,举两个小例子,跟你聊聊目前消息队列的一些使用场景. 比如消息队列在复杂系统中的解耦,又比如消息队列在高并发下的场景如果让流量变得更平缓. 随后我会跟你 ...
- day54 js基础
目录 一.变量 二.数据类型 1 数值类型(number) 2 字符类型(string) 3 字符类型常用方法 4 布尔值(boolean) 5 null与undefined 6 对象 7 运算符 8 ...
- shell专题(十):Shell工具(重点)
10.1 cut cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的.cut 命令从文件的每一行剪切字节.字符和字段并将这些字节.字符和字段输出. 1.基本用法 cut [选项参数] fi ...
- c++运行程序 鼠标点击按钮 (c++)(windows)
简介 这是在黑漆漆的程序中,制造用户可点击的按钮,来决定程序下一步该作什么,的基本代码. 详解 头文件 <cstdio>和<windows.h> 结构体 //这不全别复制 st ...
- [斯坦福大学2014机器学习教程笔记]第六章-决策界限(decision boundary)
这一节主要介绍的是决策界限(decision boundary)的概念,这个概念可以帮组我们更好地理解逻辑回归的假设函数在计算什么. 首先回忆一下上次写的公式. 现在让我们进一步了解这个假设函数在什么 ...