luogu P3180 [HAOI2016]地图 仙人掌 线段树合并 圆方树
LINK:地图
考虑如果是一棵树怎么做 权值可以离散 那么可以直接利用dsu on tree+树状数组解决。
当然 也可以使用莫队 不过前缀和比较难以维护 外面套个树状数组又带了个log 套分块然后就可以了。
最暴力的当然是线段树合并了。
此时考虑这是个仙人掌 仔细画图 发现一些比较好的性质 某个点x 除了自己某个儿子的low比自己的dfn小 剩下的都大。
剩下的显然都可以造成贡献 利用dfn和low可以轻松判断 然后上线段树合并即可。
省空间的话可以直接离线 当然也可以在线做。
不过这个做法不是常规的 仙人掌一般和圆方树联系在一起。
直接从仙人掌想到构造圆方树 然后 那么就转换成上面的问题了。
一个细节:非负整数 包括0 别犯sb错误。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<ctime>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<algorithm>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<bitset>
#include<list>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#define RE register
#define ll long long
#define putl(x) printf("%lld\n",x)
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define get(x) x=read()
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define vep(p,n,i) for(int i=p;i<n;++i)
#define fep(n,p,i) for(int i=n;i>=p;--i)
#define pii pair<int,int>
#define mod 998244353
#define sum0(i) t[i].sum0
#define sum1(i) t[i].sum1
#define pb push_back
#define l(i) t[i].l
#define r(i) t[i].r
#define mk make_pair
#define S second
#define F first
using namespace std;
char *fs,*ft,buf[1<<15];
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=100010,maxn=150010;
int n,m,Q,top,cnt,len,maxx,id,ans0,ans1,ss;
int dfn[MAXN],low[MAXN],root[MAXN],s[MAXN],q[MAXN],ans[MAXN];
int lin[MAXN],ver[maxn<<1],nex[maxn<<1],a[MAXN];
vector<pii>g[MAXN];
struct wy
{
int l,r;
int sum1,sum0;
}t[MAXN*21];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void modify(int &p,int l,int r,int x)
{
if(!p)p=++id;
if(l==r)return sum1(p)=1,void();
int mid=(l+r)>>1;
if(x<=mid)modify(l(p),l,mid,x);
else modify(r(p),mid+1,r,x);
sum1(p)=sum1(l(p))+sum1(r(p));
sum0(p)=sum0(l(p))+sum0(r(p));
}
inline int merge(int x,int y,int l,int r)
{
if(!x||!y)return x|y;
if(l==r)
{
if(sum0(x)&&sum0(y))return x;
if(sum0(x)&&sum1(y))return y;
if(sum1(x)&&sum0(y))return x;
sum0(x)=1;sum1(x)=0;
return x;
}
int mid=(l+r)>>1;
l(x)=merge(l(x),l(y),l,mid);
r(x)=merge(r(x),r(y),mid+1,r);
sum1(x)=sum1(l(x))+sum1(r(x));
sum0(x)=sum0(l(x))+sum0(r(x));
return x;
}
inline void ask(int p,int l,int r,int L,int R)
{
if(L<=l&&R>=r)
{
ans0+=sum0(p);
ans1+=sum1(p);
return;
}
int mid=(l+r)>>1;
if(L<=mid)ask(l(p),l,mid,L,R);
if(R>mid)ask(r(p),mid+1,r,L,R);
}
inline void dfs(int x)
{
s[++top]=x;dfn[x]=low[x]=++cnt;
modify(root[x],0,maxx,a[x]);
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!dfn[tn])
{
dfs(tn);
low[x]=min(low[x],low[tn]);
if(low[tn]>=dfn[x])
{
int y=s[top];ss=0;
while(y!=x)
{
q[++ss]=y;
y=s[--top];
}
rep(1,ss,i)root[x]=merge(root[x],root[q[i]],0,maxx);
}
}
else low[x]=min(low[x],dfn[tn]);
}
vep(0,g[x].size(),i)
{
ans0=ans1=0;
ask(root[x],0,maxx,0,min(maxx,ans[g[x][i].S]));
if(g[x][i].F==0)ans[g[x][i].S]=ans0;
else ans[g[x][i].S]=ans1;
}
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(m);
rep(1,n,i)get(a[i]),maxx=max(maxx,a[i]);
rep(1,m,i)
{
int get(x),get(y);
add(x,y);add(y,x);
}
get(Q);
rep(1,Q,i)
{
int get(op);
int get(x),get(y);
g[x].pb(mk(op,i));
ans[i]=y;
}
dfs(1);
rep(1,Q,i)put(ans[i]);
return 0;
}
luogu P3180 [HAOI2016]地图 仙人掌 线段树合并 圆方树的更多相关文章
- 圆方树&广义圆方树[学习笔记]
仙人掌 圆方树是用来解决仙人掌图的问题的,那什么是仙人掌图呢? 如图,不存在边同时属于多个环的无向连通图是一棵仙人掌 圆方树 定义 原先的仙人掌图,通过一些奇妙的方法,可以转化为一棵由圆点,方点和树边 ...
- 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)
orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...
- UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ23.html 题目传送门 - UOJ#23 题意 给定一个有 n 个节点的仙人掌(可能有重边). 对于所有 ...
- 仙人掌&圆方树学习笔记
仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...
- 仙人掌 && 圆方树 && 虚树 总结
仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...
- UOJ.87.mx的仙人掌(圆方树 虚树)(未AC)
题目链接 本代码10分(感觉速度还行..). 建圆方树,预处理一些东西.对询问建虚树. 对于虚树上的圆点直接做:对于方点特判,枚举其所有儿子,如果子节点不在该方点代表的环中,跳到那个点并更新其val, ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
- 圆方树简介(UOJ30:CF Round #278 Tourists)
我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...
- 【题解】Uoj#30 Tourist(广义圆方树+树上全家桶)
[题解]Uoj#30 Tourist(广义圆方树+树上全家桶) 名字听起来很霸气其实算法很简单.... 仙人掌上的普通圆方树是普及题,但是广义圆方树虽然很直观但是有很多地方值得深思 说一下算法的流程: ...
随机推荐
- MSIL入门(一)C#代码与IL代码对比
基础概念 Microsoft中间语言(MSIL),也成为通用中间语言(CIL),是一组与平台无关的指令,由特定于语言的编译器从源代码生成.MSIL是独立于平台的,因此,他可以在任何公共语言基础架构支持 ...
- Linux下对拍(A+B问题)
对拍代码 #include<bits/stdc++.h> using namespace std; int main(){ for(int i=1;;i++){ system(" ...
- unity spine 对翻转和大小的控制
spine-unity怎么决定我的Spine模型的大小? Spine使用 1像素:1单位.意思是,如果你只是包含图像在你的骨架中,并且没有任何旋转和缩放,在Spine中该图像的1个像素就对应1个单位高 ...
- python爬虫拉钩网:{'msg': '您操作太频繁,请稍后再访问', 'clientIp': '113.57.176.181', 'success': False}
反爬第一课: 在打印html.text的时候总会提示 {'success': False, 'msg': '您操作太频繁,请稍后再访问', 'clientIp': '113.14.1.254'} 需要 ...
- CRM【第一篇】: 权限组件之权限控制
1. 问:为什么程序需要权限控制? 答:生活中的权限限制,① 看灾难片电影<2012>中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临:② 屌丝们,有没有想过为什么那些长得漂亮身 ...
- C++算法 链式前向星存图
这个东西恶心了我一阵子,那个什么是什么的上一个一直是背下来的,上次比赛忘了,回来有个题也要用,只能再学一遍,之前也是,不会为什么不学呢.我觉得是因为他们讲的不太容易理解,所以我自己给那些不会的人们讲一 ...
- echarts爬坑 : 怎么Line折线图设置symbol:none后Label不见了?
用 echarts 时遇到了一个奇奇怪怪的问题. 这是一张折线图. 本来这个图是有数字显示的. series : [ { name:'搜索引擎', type:'line', stack: '总量', ...
- MacOS中Mysql设置默认字符集
一.查看字符集 mysql> show variables like 'character%'; +--------------------------+-------------------- ...
- ubuntu DEBIAN_FRONTEND环境变量用法
DEBIAN_FRONTEND环境变量,告知操作系统应该从哪儿获得用户输入.如果设置为"noninteractive",你就可以直接运行命令,而无需向用户请求输入(所有操作都是非交 ...
- navcat 增删改查
navcat // sql 语句结尾的地方需要 设置为空 SELECT * FROM users ; UPDATE users SET uname = 'hezhi' WHERE uid = 3 // ...