题解:AT_joisc2013_spy スパイ (Spy)
这道题我一直在想怎么用扫描线来做,后面实在是没招了,然后再仔细一看数据范围,发现只要
进入正题,我们先转换一下题目。对于每个间谍计划输入的
那么如何处理这个问题呢?我们可以使用 DFS 序来解决这个问题。
设在深搜时
设 JOI 社,IOI 社形成的树的 DFS 序分别为
这个式子长得很像二维偏序,但是我不会打。所以我们重新看一下数据范围,发现
于是我们可以再转换一下来求上面那个式子。我们把
那么,我们就可以运用二维差分的思想,每次读入一个二元组
差分部分时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10,M=5e5+10;
int dfn1[N],dfn2[N],num=0,siz1[N],siz2[N];
vector<int> g[N],p[N];
inline void dfs(int u,int fa){
dfn1[u]=++num;
siz1[u]=1;
for(int v:g[u]){
if(v==fa)continue;
dfs(v,u);
siz1[u]+=siz1[v];
}
return;
}
inline void dfs2(int u,int fa){
dfn2[u]=++num;
siz2[u]=1;
for(int v:p[u]){
if(v==fa)continue;
dfs2(v,u);
siz2[u]+=siz2[v];
}
return;
}
int n,m,root1,root2,q;//第一棵树的根节点和第二棵树的根节点
int s[N][N];
inline void update(int x,int y,int a,int b){//将以(x,y)为左下角,(a,b)为右上角的矩形全部加1
s[x][y]+=1;
s[x][b+1]-=1;
s[a+1][y]-=1;
s[a+1][b+1]+=1;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1,x,y;i<=n;i++){
cin>>x>>y;
if(x!=0)g[x].push_back(i),g[i].push_back(x);
else root1=i;
if(y!=0)p[y].push_back(i),p[i].push_back(y);
else root2=i;
}
dfs(root1,0);
num=0;dfs2(root2,0);
//for(int i=1;i<=n;i++)cout<<"dfn1["<<i<<"]="<<dfn1[i]<<" ";cout<<"\n"; for(int i=1;i<=n;i++)cout<<"dfn2["<<i<<"]="<<dfn2[i]<<" ";cout<<"\n";
for(int i=1,x,y;i<=m;i++){
cin>>x>>y;
update(dfn1[x],dfn2[y],dfn1[x]+siz1[x]-1,dfn2[y]+siz2[y]-1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
//cout<<s[i][j]<<" ";
}
//cout<<"\n";
}
for(int i=1;i<=n;i++)cout<<s[dfn1[i]][dfn2[i]]<<"\n";
return 芙芙天下第一!;
}