T1:对于每条边,求删了这条边原图能否成为二分图,点边规模2e6
解法:首先判掉无奇环和一个奇环的情况
一条边合法当且仅当其属于所有奇环的交集且不属于任何一个偶环(会构成新的奇环)
那就弄个dfs树,对于每条返祖边树上差分一下,奇环+1偶环-1,最后看差分值是否为奇环个数即可
Code:
#include
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e6+5;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=1;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int dep[N],pt[N],f[N],cnt,tmp;
void dfs(int v,int fa){
pt[v]=1;
for(int i=head[v];i;i=nxt[i]){
if(i==(fa^1)) continue;
int y=vis[i];
if(!pt[y]) dep[y]=dep[v]+1,dfs(y,i),f[v]+=f[y];
else{
if(dep[y]>dep[v]) continue;
if((dep[v]-dep[y]+1)&1) ++f[v],--f[y],++cnt,tmp=i>>1;
else --f[v],++f[y];
}
}
}
int ans[N],cntans=0;
inline void dfs2(int v,int fa){
pt[v]=1;
if(f[v]==cnt) ans[++cntans]=fa>>1;
for(int i=head[v];i;i=nxt[i]) if(!pt[vis[i]]) dfs2(vis[i],i);
}
int main(){
int n=read(),m=read();
for(int x,y,i=1;i<=m;i++){
x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++) if(!pt[i]) dep[i]=1,dfs(i,0);
if(!cnt){
cout<<m<<"\n";
for(int i=1;i<=m;i++) cout<<i<<" ";
return 0;
}
memset(pt,0,sizeof(pt));
for(int i=1;i<=n;i++) if(!pt[i]) dfs2(i,0);
if(cnt==1) ans[++cntans]=tmp;
sort(ans+1,ans+cntans+1);
cout<<cntans<<"\n";
for(int i=1;i<=cntans;i++) cout<<ans[i]<<" ";
return 0;
}
T2:一个字符串和一个数组,数组某一位的值表示一个字符串的后缀,支持在前端插入一个字符,单点修改数组内某个位置的值,查询数组某个区间内的所有后缀中字典序最小的
解法:显然后缀平衡树,顺便%一发zxyoi考场现推后缀平衡树模板AC
其实可以把串倒过来,然后线段树维护数组每个位置,区间求min,min的比较用二分哈希即可, n l o g 2 n nlog^2n nlog2n但可能会被卡常
#include
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e6+5;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=1;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int dep[N],pt[N],f[N],cnt,tmp;
void dfs(int v,int fa){
pt[v]=1;
for(int i=head[v];i;i=nxt[i]){
if(i==(fa^1)) continue;
int y=vis[i];
if(!pt[y]) dep[y]=dep[v]+1,dfs(y,i),f[v]+=f[y];
else{
if(dep[y]>dep[v]) continue;
if((dep[v]-dep[y]+1)&1) ++f[v],--f[y],++cnt,tmp=i>>1;
else --f[v],++f[y];
}
}
}
int ans[N],cntans=0;
inline void dfs2(int v,int fa){
pt[v]=1;
if(f[v]==cnt) ans[++cntans]=fa>>1;
for(int i=head[v];i;i=nxt[i]) if(!pt[vis[i]]) dfs2(vis[i],i);
}
int main(){
int n=read(),m=read();
for(int x,y,i=1;i<=m;i++){
x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++) if(!pt[i]) dep[i]=1,dfs(i,0);
if(!cnt){
cout<<m<<"\n";
for(int i=1;i<=m;i++) cout<<i<<" ";
return 0;
}
memset(pt,0,sizeof(pt));
for(int i=1;i<=n;i++) if(!pt[i]) dfs2(i,0);
if(cnt==1) ans[++cntans]=tmp;
sort(ans+1,ans+cntans+1);
cout<<cntans<<"\n";
for(int i=1;i<=cntans;i++) cout<<ans[i]<<" ";
return 0;
}
T3:雅礼WC2019集训traffic