题目链接:

[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;
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/10703278.html

[APIO2017]斑斓之地——可持久化线段树相关推荐

  1. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  2. SP10628 COT - Count on a tree (树剖+可持久化线段树)

    题意: 给定一个包含 N 个结点的树. 树节点从 1 到 N编号..每个节点有一个整数权值. 我们会要求您执行以下操作: u v k : 询问从节点 u 到 节点 v 的路径上的第k小的权值 输入 在 ...

  3. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  4. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

  5. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  6. 【模板】可持久化线段树 1(主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  7. LGOJ P3919【模板】可持久化数组(可持久化线段树/平衡树)

    代码 //可持久化线段树 #include <cstdio> using namespace std;struct node {node *Lnode,*Rnode;int val;voi ...

  8. 【可持久化线段树?!】rope史上最全详解

    https://www.luogu.org/problemnew/show/P3919 看到上面链接中的题时,我在学会可持久化线段树的同时,第一次学会了一个非常屌(cai)的STL大法--rope!! ...

  9. 洛谷P3919可持久化线段树

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目提供者HansBug 站长团 评测方式云端评测 标签O2优化高性能 难度提高+/省选- 时空限制3000ms / 512MB 有了可持久 ...

最新文章

  1. Docker(一):Docker入门教程
  2. dotproject 文件下载错误
  3. 如何设计企业内部的数据平台?
  4. android Activity runOnUiThread() 方法的使用
  5. js制作动态图片时钟
  6. echarts 直方图加正态_在频数直方图上绘制正态分布曲线
  7. (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  8. 十款磁盘碎片整理工具
  9. Markdown 语法手册 (完整整理版)转抄
  10. 华为3COM正式更名为『杭州华三通信技术有限公司(H3C)』
  11. 微信小程序开发得会议扫码签到系统
  12. 【kong系列十一】之JWT插件RSA256非对称加密使用
  13. 【身份鉴别-身份标识】Linux系统用户及用户组管理
  14. 科大讯飞胡郁:我所领导的超脑项目,代表了AI的未来
  15. redis,Spring Cache,Mango,ES
  16. 转行做前端应该具备哪些素质?干货分享
  17. AngularCI/CD:Error: initial exceeded maximum budget
  18. goland中出现declared but not used 如何解决
  19. WebSocket聊天室
  20. 平台搭建淘宝店铺怎么运营?

热门文章

  1. 计算机科学前沿期刊,FCS|期刊动态:《计算机科学前沿》2021年第一期精彩文章...
  2. 基于AI视觉技术构建柔性生产数字化车间
  3. 第十四章 我国农村乡镇企业发展
  4. 新买的笔记本如何安装计算机,新电脑买回来要怎么做【经验分享】
  5. 对比文本 python学习 工具类代码
  6. 科技云报道原创:没有一个行业,能拒绝“通信中台”的诱惑
  7. 查看计算机上隐藏用户,Win732位旗舰版系统下如何查看与删除隐藏账户【图】
  8. 树莓派oled IP显示
  9. linux调试MCX314AL过程
  10. 用 Java 实现贪吃蛇小游戏