社区讨论
QWQ,求条,悬二关
P4618[SDOI2018] 原题识别参与者 2已保存回复 4
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @mir4keny
- 此快照首次捕获于
- 2025/12/04 15:39 3 个月前
- 此快照最后确认于
- 2025/12/06 14:30 2 个月前
CPP
#include<bits/stdc++.h>
#define ui unsigned int
using namespace std;
int n,p;
ui SA,SB,SC;
int s;
vector<int>g[(int)2e5+10];
ui rng61(){
SA ^= SA << 16;
SA ^= SA >> 5;
SA ^= SA << 1;
ui t = SA;
SA = SB;
SB = SC;
SC ^= t ^ SA;
return SC;
}
void addedge(int x,int y){
g[y].push_back(x);
g[x].push_back(y);
}
struct node{
int l,r,id,lcaa;
}q[(int)2e5+10];
map<int,int>mp;
int a[(int)2e5+10],m;
int fa[(int)2e5+10][25];
int ord[(int)4e5+10];
int cntt[(int)2e5+10];
int idx,cnt,ans;
int st[(int)2e5+10];
int b[(int)2e5+10];
int ed[(int)2e5+10];
int dep[(int)2e5+10];
int res[(int)2e5+10];
int id[(int)2e5+10];
int cnt2[(int)2e5+10];
void add(int x){
cntt[ord[x]]++;
if(cntt[ord[x]]==1){
++cnt2[a[ord[x]]];
if(cnt2[a[ord[x]]]==1)ans++;
}
if(cntt[ord[x]]==2){
cnt2[a[ord[x]]]--;
if(cnt2[a[ord[x]]]==0)ans--;
}
}
void sub(int x){
cntt[ord[x]]--;
if(cntt[ord[x]]==1){
++cnt2[a[ord[x]]];
if(cnt2[a[ord[x]]]==1)ans++;
}
if(cntt[ord[x]]==0){
cnt2[a[ord[x]]]--;
if(cnt2[a[ord[x]]]==0)ans--;
}
}
void dfs(int x,int faa){
ord[++idx]=x;
st[x]=idx;
for(int i=0;i<g[x].size();i++){
int y=g[x][i];
if(y==faa)continue;
dep[y]=dep[x]+1;
fa[y][0]=x;
dfs(y,x);
}
ord[++idx]=x;
ed[x]=idx;
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--){
if(dep[fa[x][i]]>=dep[y]){
x=fa[x][i];
}
}
if(x==y)return x;
for(int i=20;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i],y=fa[y][i];
}
}
return fa[x][0];
}
bool cmp(node x,node y){
if(id[x.l]!=id[y.l])return id[x.l]<id[y.l];
return x.r<y.r;
}
void solve(){
scanf("%d%d%u%u%u", &n, &p, &SA, &SB, &SC);
s=sqrt(2*n);
for(int i = 2; i <= p; i++)
addedge(i - 1, i);
for(int i = p + 1; i <= n; i++){
addedge((rng61() % (ui)(i-1))+(ui)1, i);
}
for(int i=1;i<=2*n;i++)id[i]=(i-1)/s+1;
for(int i = 1; i <= n; i++)
a[i] = (int)((rng61() % (ui)(n)) + 1),b[i]=a[i];
sort(b+1,b+n+1);
int len=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+len+1,a[i])-b;
}
cin>>m;
dep[0]=-1;
dfs(1,0);
for(int i=1;i<=20;i++){
for(int j=1;j<=n;j++){
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
int js=0;
for(int i=1;i<=m;i++){
int op,x,y;
cin>>op>>x>>y;;
if(op!=1)continue;
js++;
q[js].id=js;
if(st[x]>st[y])swap(x,y);
if(lca(x,y)==x||lca(x,y)==y)q[js].l=st[x],q[js].r=st[y];
if(lca(x,y)!=x&&lca(x,y)!=y)q[js].l=min(ed[x],st[y]),q[js].r=max(st[y],ed[x]),q[js].lcaa=lca(x,y);
}
sort(q+1,q+js+1,cmp);
int l=1,r=0;
ans=0;
for(int i=1;i<=js;i++){
while(l<q[i].l)sub(l++);
while(l>q[i].l)add(--l);
while(r<q[i].r)add(++r);
while(r>q[i].r)sub(r--);
if(q[i].lcaa){
add(st[q[i].lcaa]);
}
res[q[i].id]=ans;
if(q[i].lcaa){
sub(st[q[i].lcaa]);
}
}
for(int i=1;i<=js;i++)cout<<res[i]<<'\n';
for(int i=1;i<=n;i++){
g[i].clear();
cntt[i]=0;
cnt2[a[i]]=0;
st[i]=0,ed[i]=0;
}
for(int i=0;i<=20;i++){
for(int j=1;j<=n;j++)fa[j][i]=0;
}
idx=0;
}
signed main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
期望30pts的树上莫队,实际0pts,求条,悬二关
回复
共 4 条回复,欢迎继续交流。
正在加载回复...