[HAOI2016] 地图
仙人掌,所以先建一颗圆方树,这里使用广义圆方树就可以了,然后题目就变成了查询子树内点权
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#pragma GCC optimeze(3)
#pragma GCC optimeze(2)
#define PII pair<int, int>
#define pb push_back
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define inv(x) (qpow(x,mod-2))
#define blong(i) ((i+K-1)/K)
using namespace std;
const int N=1e6+10;
const int K=1e3+5;
double eps=1e-6;
inline int read(){
char ch=getchar();bool f=0;int x=0;
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1;
for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
if(f==1)x=-x;return x;
}
struct que{
int l,r,x,opt,id;
}qu[N];
int n,m,a[N],dfc,dfn[N],low[N],V,L[N],R[N],rk[N],blong[K*K],q,b[2][K],bj[K*K],ans[N];
stack<int>S;
vector<int>G[N],G2[N];
void tj(int t){
dfn[t]=low[t]=++dfc;
S.push(t);
for(auto to:G[t]){
if(!dfn[to]){
tj(to);
low[t]=min(low[t],low[to]);
if(low[to]==dfn[t]){
V++;
G2[V].pb(t),G2[t].pb(V);
while(S.top()!=to){
int x=S.top();S.pop();
G2[x].pb(V),G2[V].pb(x);
}
int x=S.top();S.pop();
G2[x].pb(V),G2[V].pb(x);
}
}
else low[t]=min(low[t],dfn[to]);
}
}
void dfs(int t,int fa){
L[t]=++dfc,rk[dfc]=t;
for(auto to:G2[t]){
if(to==fa)continue;
dfs(to,t);
}
R[t]=dfc;
}
bool cmp(que a,que b){
if(blong(a.l)!=blong(b.l))return blong(a.l)<blong(b.l);
else return (blong(a.l)&1? a.r<b.r:a.r>b.r);
}
void add(int x){
if(rk[x]>n)return;
x=a[rk[x]];
if(bj[x])b[bj[x]&1][blong(x)]--;
bj[x]++;
b[bj[x]&1][blong(x)]++;
}
void del(int x){
if(rk[x]>n)return;
x=a[rk[x]];
b[bj[x]&1][blong(x)]--;
bj[x]--;
if(bj[x])b[bj[x]&1][blong(x)]++;
}
int query(int opt,int x){
int ans=0;
for(int i=1;i<blong(x);i++)ans+=b[opt][i];
for(int i=(blong(x)-1)*K+1;i<=x;i++)ans+=((bj[i]&1)==opt&&bj[i]);
return ans;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
srand(time(0));
cin>>n>>m;
V=n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++){
int u,v;cin>>u>>v;
G[u].pb(v),G[v].pb(u);
}
for(int i=1;i<=n;i++){
if(!dfn[i])tj(i);
}
dfs(1,0);
int q;cin>>q;
for(int i=1;i<=q;i++){
int t;
cin>>qu[i].opt>>t>>qu[i].x;
qu[i].id=i,qu[i].l=L[t],qu[i].r=R[t];
}
sort(qu+1,qu+1+q,cmp);
int l=1,r=0;
for(int i=1;i<=q;i++){
while(l>qu[i].l)add(--l);
while(r<qu[i].r)add(++r);
while(l<qu[i].l)del(l++);
while(r>qu[i].r)del(r--);
ans[qu[i].id]=query(qu[i].opt,qu[i].x);
}
for(int i=1;i<=q;i++)cout<<ans[i]<<'\n';
return 0;
}
本文作者:Xdik
本文链接:https://www.cnblogs.com/Xdik/p/18710134
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步