[LOJ2310][APIO2017]斑斓之地——可持久化线段树
题目链接:
将不是河流的格子染成白色,是河流的格子染成黑色,那么连通块数就是白色格子数$-1*2$的联通白色格子数$-2*1$的联通白色格子数$+2*2$的联通白色格子数。
我们考虑每个格子与它左边、上边、左上三个格子的连通性(同为白色视为联通)。
为了方便起见,对于每个$2*2$的格子,我们将它编号,从左往右、从上往下依次编号为$1,2,3,4$。
我们将$1,2,3$与$4$的连通性都归为$4$号格子对答案的贡献。
显然联通情况有$5$种:$1,2,3,4$、$2,3,4$、$2,4$、$3,4$、$4$。
对于第一种情况,$4$号点对答案的贡献为$1-1-1+1=0$
对于第二种情况,$4$号点对答案的贡献为$1-1-1=-1$
对于第三、四种情况,$4$号点对答案的贡献为$1-1=0$
对于第五种情况,$4$号点对答案的贡献为$1$
可以发现第一、三、四种情况对答案没有影响,而第二、五种情况只会出现在一个连通块的最左边和最上边两排(有一种特殊情况后边再说明)。
对于最左边,如果有一个格子是第二种情况,那么在这个点的同一行的最左边那个点就会是第五种情况,这两个格子的贡献抵消。
对于最上边,如果有一个格子是第二种情况,那么在这个点的同一列的最上边那个点就会是第五种情况,这两个格子的贡献抵消。
但可以发现最左上的那个格子是第五种情况却没有其他格子与它的贡献抵消,所以只有这个格子对这个连通块有贡献。
这样有一个特例就是河流被这个连通块包围起来,即这个连通块是中空的。
那么右边和下边也会出现第二、五种情况,而对于右下两部分格子中的左上那个格子是第二种情况,会将上面那个对连通块有贡献的格子抵消掉(如下图所示),所以对于这种情况特判一下将答案加一即可。
剩下的就是如何统计上述的四种连通块的个数。
因为地图总大小是$4*10^{10}$,无法对每个点存是否有上述四种贡献。
但可以发现河流的格子最多只有$2*10^5$个格子,我们分别记录哪些格子没有上述四种贡献,然后用总贡献减一下即可。
对于整个地图将横坐标作为版本,对纵坐标建线段树即建立四棵可持久化线段树分别维护上述四种信息。
注意彩虹蛇可能走之前走过的格子,要判重避免重复统计。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,q,k;
map<int,int>mp[200010];
int px[200010];
int py[200010];
int tot;
int mx1,mx2,mn1,mn2;
int fx,fy;
int size;
vector<int>t1[200010];
vector<int>t2[200010];
vector<int>t3[200010];
vector<int>t4[200010];
char ch[200010];
int a,b,c,d;
ll ans;
struct lty
{
int cnt;
int root[200010];
int ls[4000010];
int rs[4000010];
int sum[4000010];
void updata(int &rt,int pre,int l,int r,int k)
{
rt=++cnt;
ls[rt]=ls[pre];
rs[rt]=rs[pre];
sum[rt]=sum[pre]+1;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
updata(ls[rt],ls[pre],l,mid,k);
}
else
{
updata(rs[rt],rs[pre],mid+1,r,k);
}
}
int query(int x,int y,int l,int r,int L,int R)
{
if(!y)
{
return 0;
}
if(L<=l&&r<=R)
{
return sum[y]-sum[x];
}
int mid=(l+r)>>1;
int res=0;
if(L<=mid)
{
res+=query(ls[x],ls[y],l,mid,L,R);
}
if(R>mid)
{
res+=query(rs[x],rs[y],mid+1,r,L,R);
}
return res;
}
}tr1,tr2,tr3,tr4;
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&q);
scanf("%d%d",&fx,&fy);
tot++;
px[tot]=fx,py[tot]=fy;
mx1=mn1=fx,mx2=mn2=fy;
mp[fx][fy]=1;
if(k)
{
scanf("%s",ch+1);
}
for(int i=1;i<=k;i++)
{
tot++;
if(ch[i]=='N')
{
fx--;
}
else if(ch[i]=='S')
{
fx++;
}
else if(ch[i]=='E')
{
fy++;
}
else
{
fy--;
}
px[tot]=fx,py[tot]=fy;
mx1=max(mx1,fx);
mn1=min(mn1,fx);
mx2=max(mx2,fy);
mn2=min(mn2,fy);
mp[fx][fy]=1;
}
for(int i=1;i<=tot;i++)
{
int x=px[i],y=py[i];
if(mp[x][y]==2)
{
continue;
}
mp[x][y]=2;
t1[x].push_back(y);
if(y>1)t2[x].push_back(y);
if(y<m&&!mp[x][y+1])t2[x].push_back(y+1);
if(x>1)t3[x].push_back(y);
if(x<n&&!mp[x+1][y])t3[x+1].push_back(y);
if(x>1&&y>1)t4[x].push_back(y);
if(x<n&&y<m&&!mp[x+1][y+1])t4[x+1].push_back(y+1);
if(x<n&&y>1&&!mp[x][y-1]&&!mp[x+1][y])t4[x+1].push_back(y);
if(x>1&&y<m&&!mp[x-1][y]&&!mp[x-1][y+1]&&!mp[x][y+1])t4[x].push_back(y+1);
}
for(int i=1;i<=n;i++)
{
tr1.root[i]=tr1.root[i-1];
tr2.root[i]=tr2.root[i-1];
tr3.root[i]=tr3.root[i-1];
tr4.root[i]=tr4.root[i-1];
size=t1[i].size();
for(int j=0;j<size;j++)
{
tr1.updata(tr1.root[i],tr1.root[i],1,m,t1[i][j]);
}
size=t2[i].size();
for(int j=0;j<size;j++)
{
tr2.updata(tr2.root[i],tr2.root[i],1,m,t2[i][j]);
}
size=t3[i].size();
for(int j=0;j<size;j++)
{
tr3.updata(tr3.root[i],tr3.root[i],1,m,t3[i][j]);
}
size=t4[i].size();
for(int j=0;j<size;j++)
{
tr4.updata(tr4.root[i],tr4.root[i],1,m,t4[i][j]);
}
}
while(q--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
ans=0;
if(a<mn1&&c>mx1&&b<mn2&&d>mx2)
{
ans++;
}
ans+=1ll*(d-b)*(c-a)-tr1.query(tr1.root[a-1],tr1.root[c],1,m,b,d);
ans-=1ll*(d-b-1)*(c-a)-tr2.query(tr2.root[a-1],tr2.root[c],1,m,b+1,d);
ans-=1ll*(d-b)*(c-a-1)-tr3.query(tr3.root[a],tr3.root[c],1,m,b,d);
ans+=1ll*(d-b-1)*(c-a-1)-tr4.query(tr4.root[a],tr4.root[c],1,m,b+1,d);
printf("%lld\n",ans);
}
return 0;
}
[LOJ2310][APIO2017]斑斓之地——可持久化线段树的更多相关文章
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- 【BZOJ-2653】middle 可持久化线段树 + 二分
2653: middle Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1298 Solved: 734[Submit][Status][Discu ...
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- 【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树
3653: 谈笑风生 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 628 Solved: 245[Submit][Status][Discuss] ...
- 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树
没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...
- 【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队
看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: #include<bits/stdc++.h&g ...
- 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破 ...
- 【BZOJ 3524】【Poi2014】Couriers 可持久化线段树
为什么这个主席树叫可持久化线段树,我不知道,具体得问达神.我无限T,然后DaD3zZ一针见血地指出了我的N*50爆内存导致无限编译超时O)ZO)ZO)Z真是太神啦.以图为鉴: 达神题解传送门:http ...
随机推荐
- C#网络请求与JSON解析
最新学校的海康摄像头集控平台(网页端)不能在win10里登录,我寻思着拿海康的c# demo直接改. 首先得解决权限问题,每个教师任教不同年级,只能看到自己所在年级的设备,涉及到登录,在此记录一下C# ...
- JS 事件绑定,监听,委托(代理)
我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等.这些名词是什么意思呢,有什么作用呢? 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元 ...
- Hacking Box Droopy: v0.2
概述: 目标:get flag 下载链接: https://www.vulnhub.com/entry/droopy-v02,143/ 工具: kail linux 开工 1)扫描开道: # netd ...
- AOP中使用Aspectj对接口访问权限进行访问控制
切面编程的应用案例比较多,在统一的日志处理,鉴权过程中都会用的AOP原理,本文主要针对对进口的访问权限进行控制为例,说明 切面编程的使用: 1.使用Aspectj的方式进行切面编程: 2.编码环境,s ...
- Android细笔记--DataStorage
Shared Preferences 即使应用被杀了,shared preference也还是存在的 Internal Storage 创建于internal的文件只对本应用开放权限,即使手机用户本身 ...
- 解决service iptables save出错please try to use systemctl
# service iptables save The service command supports only basic LSB actions (start, stop, restart, t ...
- Java - String 的字面量、常量池、构造函数和intern()函数
一.内存中的 String 对象 Java 的堆和栈 对于基本数据类型变量和对象的引用,也就是局部变量表属于栈内存: 而通过 new 关键字和 constructor 创建的对象存放在堆内存: 直接的 ...
- Svn在工作中的实践感悟
Svn是一款管理项目代码的版本控制系统,是基于集中式的版本控制系统.在工作中,由于实际开发工作的需要,部门是使用Svn来管理日常的项目开发任务.使用这么长时间了,来谈谈对Svn的感悟. 首先,说下工作 ...
- 树莓派Ubuntu 16.04 MATA系统 修改用户文件夹名后,提示configure it with blueman-service
自从修改了树莓派的Ubuntu 16.04 MATA 系统的 /home/ 下的用户文件夹名后,使用vncserver远程操作,看到桌面每次都提示 Configured directory for i ...
- MongoDB在Linux系统下的安装与启动
Mongodb介绍 MongoDB是一个开源文档数据库,提供高性能,高可用性和自动扩展,官方文档:https://docs.mongodb.com/manual/introduction/ Mongo ...