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]地图 仙人掌 线段树合并 圆方树的更多相关文章

  1. 圆方树&广义圆方树[学习笔记]

    仙人掌 圆方树是用来解决仙人掌图的问题的,那什么是仙人掌图呢? 如图,不存在边同时属于多个环的无向连通图是一棵仙人掌 圆方树 定义 原先的仙人掌图,通过一些奇妙的方法,可以转化为一棵由圆点,方点和树边 ...

  2. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

  3. UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ23.html 题目传送门 - UOJ#23 题意 给定一个有 n 个节点的仙人掌(可能有重边). 对于所有 ...

  4. 仙人掌&圆方树学习笔记

    仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...

  5. 仙人掌 && 圆方树 && 虚树 总结

    仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...

  6. UOJ.87.mx的仙人掌(圆方树 虚树)(未AC)

    题目链接 本代码10分(感觉速度还行..). 建圆方树,预处理一些东西.对询问建虚树. 对于虚树上的圆点直接做:对于方点特判,枚举其所有儿子,如果子节点不在该方点代表的环中,跳到那个点并更新其val, ...

  7. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  8. 圆方树简介(UOJ30:CF Round #278 Tourists)

    我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...

  9. 【题解】Uoj#30 Tourist(广义圆方树+树上全家桶)

    [题解]Uoj#30 Tourist(广义圆方树+树上全家桶) 名字听起来很霸气其实算法很简单.... 仙人掌上的普通圆方树是普及题,但是广义圆方树虽然很直观但是有很多地方值得深思 说一下算法的流程: ...

随机推荐

  1. RISC-V发展现状

    欲观原文,请君移步 面对xilinx和ARM联合打造的生态链,FPGA底层RTL逻辑开发人员变得可有可无,有的公司软件工程师都可以直接上手,这让传统的FPGA人员面临着一个尴尬的境地,而RISC-V的 ...

  2. java NIO 实例之多人聊天

    关键抽象 1.定义一个HashMap<String,SocketChannel>用户存储每个用户的管道. 2.服务端监听read事件,获取消息后轮询hashmap发送消息给用户模型内的所有 ...

  3. 使用wsl2時碰到的問題

    1.啓動wsl系统时出现“参考的对象类型不支持尝试的操作”. 解决方法: netsh winsock reset

  4. java 面向对象(二十七):注解的使用

    1. 注解的理解① jdk 5.0 新增的功能*② Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理.通过使用 Annotation, ...

  5. 使用OpenCV对图片进行特征点检测和匹配(C++)

    背景 最近从不同网站下载了非常多的动漫壁纸,其中有一些内容相同,但是大小.背景颜色.色调.主人公的位置不同(例子如下).正因为如此,基础的均方误差.直方图检测等方法很难识别出这些相似的图片. 思路 O ...

  6. SQL注入环境的搭建

    使用Phpstudy搭建SQL注入环境: 1.下载phpstudy安装 2.下载sql实验环境 所用环境的代码是一个印度人的开源项目平台.里面包含了基本的各种注入类型,同时又有get和post类型,以 ...

  7. Flink之对时间的处理

    window+trigger+watermark处理全局乱序数据,指定窗口上的allowedLateness可以处理特定窗口操作的局部事件时间乱序数据 1.流处理系统中的微批 Flink内部也使用了某 ...

  8. [Qt2D绘图]-04绘制文字&&绘制路径

    注:学习自<Qt Creator 快速入门>第三版.   文档中的示例参考 Qt Example推荐:Painter Paths Example和Vector Deformation   ...

  9. Java实现简单的增删改查操作

    需求分析:通过数组 ,完成 对学生信息的 管理 (增删改查)创建1个 学生类创建1个 CRUD的类 – 学生管理类 并测试 在这个程序中我只运用了两个类进行操作 package com.hopu.de ...

  10. Win7安装Python失败 提示Setup failed

    一.安装报错 如图所示,双击Python安装包后进行安装显示Setup failed 安装失败: 二.错误排除 1.首先查看自己的计算机是否已经安装了 Win7 Service Pack 1大补丁,没 ...