卧薪尝胆,厚积薄发。
HAOI2016 地图
Date: Tue Nov 27 10:15:13 CST 2018 In Category: NoCategory

Description:

给以 $1$ 为根的一个边仙人掌,每个点有权值,求出某个点在到根的所有简单路径上的点都被封锁的情况下能到达的所有点的出现过奇数或偶数次且权值小于 $y$ 的值的个数。
$1\leqslant n\leqslant 10^5$

Solution:

先建出圆方树,那么一个点可以到达的就是圆方树的一个子树,在圆方树 $dfs$ 序上莫队 $+$ 树状数组即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
int n,m,p;
#define MAXN 200010
int val[MAXN];
#define MAXM 150010
vector<int> g[MAXN];
struct edge
{
int to,nxt;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b)
{
e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
e[++edgenum] = (edge){a,lin[b]};lin[b] = edgenum;
return;
}
int dfn[MAXN],low[MAXN],tot = 0;
stack<int> s;
int cnt;
void tarjan(int k)
{
dfn[k] = low[k] = ++tot;
s.push(k);
for(vector<int>::iterator i = g[k].begin();i != g[k].end();++i)
{
if(dfn[*i] == 0)
{
tarjan(*i);
low[k] = min(low[k],low[*i]);
if(low[*i] >= dfn[k])
{
int t;++cnt;
do
{
t = s.top();s.pop();
add(t,cnt);
}while(t != *i);
add(k,cnt);
}
}
else
{
low[k] = min(low[k],dfn[*i]);
}
}
return;
}
int rnk[MAXN],th[MAXN],siz[MAXN];
void dfs(int k)
{
rnk[k] = ++tot;th[tot] = k;siz[k] = 1;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(rnk[e[i].to] == 0)
{
dfs(e[i].to);
siz[k] += siz[e[i].to];
}
}
return;
}
struct query
{
int l,r,k,type,id,ans;
}q[MAXN];
int pos[MAXN];
bool cmp(query a,query b){return (pos[a.l] == pos[b.l] ? a.r < b.r : pos[a.l] < pos[b.l]);}
bool cmp_id(query a,query b){return a.id < b.id;}
struct BIT
{
#define MAX 1000000
int c[MAX + 1];
int lowbit(int x){return x & (-x);}
void add(int p,int x){for(int i = p;i <= MAX;i += lowbit(i))c[i] += x;return;}
int query(int p){int res = 0;for(int i = p;i >= 1;i -= lowbit(i))res += c[i];return res;}
}t[2];
int tim[MAX + 1];
void add(int v)
{
if(v == 0)return;
if(tim[v] != 0)t[tim[v] & 1].add(v,-1);
++tim[v];
t[tim[v] & 1].add(v,1);
return;
}
void rem(int v)
{
if(v == 0)return;
t[tim[v] & 1].add(v,-1);
--tim[v];
if(tim[v] != 0)t[tim[v] & 1].add(v,1);
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i)scanf("%d",&val[i]);
int a,b;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
cnt = n;
for(int i = 1;i <= n;++i)
{
if(dfn[i] == 0)tarjan(i);
}
tot = 0;
dfs(1);
int blo = sqrt(cnt);
for(int i = 1;i <= cnt;++i)pos[i] = (i - 1) / blo + 1;
scanf("%d",&p);
int loc,lim;
for(int i = 1;i <= p;++i)
{
scanf("%d%d%d",&q[i].type,&loc,&lim);
q[i].id = i;q[i].l = rnk[loc];q[i].r = rnk[loc] + siz[loc] - 1;
q[i].k = lim;
}
sort(q + 1,q + 1 + p,cmp);
for(int i = 1,l = 1,r = 0;i <= p;++i)
{
while(r < q[i].r)add(val[th[++r]]);
while(l > q[i].l)add(val[th[--l]]);
while(r > q[i].r)rem(val[th[r--]]);
while(l < q[i].l)rem(val[th[l++]]);
q[i].ans = t[q[i].type].query(q[i].k);
}
sort(q + 1,q + 1 + p,cmp_id);
for(int i = 1;i <= p;++i)printf("%d\n",q[i].ans);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡