【DS】P5311 [Ynoi2011] 成都七中
考虑点分树,找到最浅的满足条件的点,那么所有连通块符合条件的一定能以它为根来统计到。
考虑一个点 \(y\) 满足能作为颜色集合中(但不一定对答案贡献),显然是 \(x\to y\) 的路径所经过的点都满足那个偏序关系。
转化为二位偏序即可,数颜色 HH 的项链,大致按 r 排序,维护最大的 l 来贡献。
哈哈,我不会二位偏序()
节省空间的话可以在建立点分树时就搞当前重心答案。
#include
#define pb push_back
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
#define inf (int)(2e9)
#define N (int)(1e5+5)
struct node {
int l,r,id;
node(int lx,int rx,int idd) {
l=lx; r=rx; id=idd;
}
};
vectorg[N];
vectorQ[N],q,vec;
bool vis[N],used[N];
int n,m,ans[N],pre[N],sum[N],col[N],mi,rt,nwsum,sz[N];
int lowbit(int x) {
return x&(-x);
}
void add(int x,int v) {
if(x<=0) return ;
while(x<=n) sum[x]+=v,x+=lowbit(x);
}
int qry(int x) {
if(x<=0) return 0;
int res=0;
while(x) res+=sum[x],x-=lowbit(x);
return res;
}
void fd_rt(int x,int ff) {
sz[x]=1; int qwq=0;
for(int y:g[x]) {
if(vis[y]||y==ff) continue;
fd_rt(y,x); sz[x]+=sz[y];
qwq=max(qwq,sz[y]);
}
qwq=max(qwq,nwsum-sz[x]);
if(qwq=r) {
used[qwq.id]=1; q.pb(node(qwq.l,qwq.r,qwq.id));
}
}
for(int y:g[x]) {
if(vis[y]||y==ff) continue;
dfs(y,x,min(l,y),max(r,y));
}
}
bool cmp(const node &x,const node &y) {
return x.rpre[vec[j].id]) {
add(pre[vec[j].id],-1);
add(vec[j].l,1);
pre[vec[j].id]=vec[j].l;
}
++j;
}
// printf("%d %d %d\n",q[i].id,q[i].l,q[i].r);
ans[q[i].id]=qry(q[i].r)-qry(q[i].l-1);
}
for(int i=0;i