专栏文章
题解:CF2129E Induced Subgraph Queries
CF2129E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minkm8g3
- 此快照首次捕获于
- 2025/12/02 03:57 3 个月前
- 此快照最后确认于
- 2025/12/02 03:57 3 个月前
简单题。
对于这个贡献,发现我们其实并不好拆位算,貌似整体维护的比拆开更有前途。
,开了 ,我们考虑莫队,然后第 小可以直接用个值域分块去做。
可是这样有一个问题:我们莫队移动一个端点的代价就成为了 ,其中 表示 的度数。
不妨设在 的后面添加 个点,然后询问的区间对应添加后的序列改变,这样再莫队时间复杂度就是 的了。正确性显然。
CPP#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0;bool f=0;char ch=getchar();
while(ch<'0'||ch>'9')f^=(ch=='-'),ch=getchar();
while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int Maxn=1.5e5+5,B=666,V=262143+5;
int n,m,belong[Maxn*3];
struct edge{
int u,v;
}e[Maxn];
int q,ans[Maxn];
struct Query{
int l,r,k,id;
}Q[Maxn];
vector<int>a[Maxn];
int sum[Maxn];
int b[V],g[V];
inline void modify(int x,int p){
g[x/B]+=p;b[x]+=p;
}
inline int query(int k){
int now=0;
while(g[now]<k)k-=g[now++];
for(int i=now*B;i<min(262144,now*B+B);i++){
if(b[i]>=k)return i;
k-=b[i];
}assert(0);
}
int res[Maxn];
inline void moved(int x,int l,int r,int op){
if(op)modify(res[x],-1);
for(int y:a[x])
if(l<=y&&y<=r)modify(res[y],-1),modify((res[y]^=x),1),res[x]^=y;
if(!op)modify(res[x],1);
}
inline void solve(){
n=read();m=read();
for(int i=1;i<=n;i++)a[i].clear(),sum[i]=1,res[i]=0;
for(int i=0;i<=min(262143,n*2);i++)b[i]=g[i]=0;
for(int i=1;i<=m;i++){
e[i]={read(),read()};
a[e[i].u].push_back(e[i].v);
a[e[i].v].push_back(e[i].u);
sum[e[i].u]++;sum[e[i].v]++;
}
for(int i=1;i<=n;i++)sum[i]+=sum[i-1];
q=read();
for(int i=1;i<=q;i++)Q[i]={read(),read(),read(),i};
sort(Q+1,Q+1+q,[&](Query a,Query b){
if(belong[sum[a.r]]==belong[sum[b.r]]){
if(belong[sum[a.r]]&1)return a.l<b.l;
return a.l>b.l;
}
return belong[sum[a.r]]<belong[sum[b.r]];
});
int l=1,r=0;
for(int i=1;i<=q;i++){
while(Q[i].l<l)moved(--l,l,r,0);
while(Q[i].r>r)moved(++r,l,r,0);
while(Q[i].r<r)moved(r--,l,r,1);
while(Q[i].l>l)moved(l++,l,r,1);
ans[Q[i].id]=query(Q[i].k);
}
for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
for(int i=1;i<=4.5e5;i++)belong[i]=i/B;
int T=read();
while(T--)solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...