- 题意:在标准的求异或最短路的基础上,添加加边删边类的修改操作
- 思路:离线对操作按时间顺序线段树分治。
其实很好想。加一个维护到根异或和的带权可撤销并查集。
想说的是调代码的问题啦。
我调了一个上午+一个下午原因竟然是因为排序以为(x,y,t)不同,两个操作就不同了,本身大部分情况是这样的。但是自己先前给自己挖了坑,我把一开始默认的边的时间戳设的1,跟第一个操作的时间戳相同。然后我就gg了(因为只要第一个是2操作,还要加上按修改在删除前)。我也很无语,不过真的很难想到这个问题,加上一直以为自己的线段树分治里面写错了。而且调大数据的时候一定要慢,不要急,要想清楚每一步要做的什么了,慢慢分析清楚了,再下一步。
- code:
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
typedef long long ll;
int ans[N],n,m,q,up=30,Bs[31];
struct query {int opt,x,y,z,t;}s[N];
struct seg {int l,r;}T[N<<1];
struct node {int x,y;};
vector<node>Q[N<<1];
vector<int>V[N<<1];
bool cmp(query u,query v) {return u.x^v.x?u.x<v.x:(u.y^v.y?u.y<v.y:(u.t^v.t?u.t<v.t:u.opt<v.opt));}
void Build(int x,int l,int r) {
T[x]=(seg){l,r};
if(l==r)return;
int mid=(l+r)>>1;
Build(x<<1,l,mid),Build(x<<1|1,mid+1,r);
}
void Update(int x,int l,int r,int p) {
if(l<=T[x].l&&T[x].r<=r) {V[x].push_back(p);return;}
int mid=(T[x].l+T[x].r)>>1;
if(l<=mid) Update(x<<1,l,r,p);
if(r>mid) Update(x<<1|1,l,r,p);
}
bool flag=0;
void Insert(int y) {
for(int i=up;y&&i>=0;i--) {
if((y>>i)&1) {
if(!Bs[i]){Bs[i]=y;return;}
else y^=Bs[i];
}
}
}
int Mn(int y) {
for(int i=up;i>=0;i--) {
if((y>>i)&1) {
y^=Bs[i];
}
}
return y;
}
int st[N],tp,sz[N],fa[N],xos[N],we[N];
int g_fa(int x) {
if(fa[x]==x)return x;
int f=fa[x],fx=g_fa(f);
xos[x]=xos[f]^we[x];
return fx;
}
bool Union(int p) {
int x=s[p].x,y=s[p].y,z=s[p].z;
int fx=g_fa(x),fy=g_fa(y);
if(fx==fy) {Insert(z^xos[x]^xos[y]);return 0;}
else {if(sz[fx]>sz[fy])swap(fx,fy);st[++tp]=fx;fa[fx]=fy;sz[fy]+=sz[fx];we[fx]=z^xos[x]^xos[y];return 1;}
}
void _past() {
int fx=st[tp],fy=g_fa(fx);
tp--;sz[fy]-=sz[fx];fa[fx]=fx;we[fx]=xos[fx]=0;
}
void solve(int x) {
int nw[31],cnt=0;
for(int i=up;i>=0;i--)nw[i]=Bs[i];
for(int i=0;i<V[x].size();i++) {
int p=V[x][i];
cnt+=Union(p);
}
if(T[x].l==T[x].r) {
int t=T[x].l;
for(int i=0;i<Q[t].size();i++) {
int u=Q[t][i].x,v=Q[t][i].y;
int k=g_fa(u);k=g_fa(v);
int d=xos[u]^xos[v];
ans[t]=Mn(d);
}
}
else {solve(x<<1);solve(x<<1|1);}
while(cnt--) _past();
for(int i=up;i>=0;i--)Bs[i]=nw[i];
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z),s[i].t=1,s[i].opt=1;
scanf("%d",&q);
int tot=m;
for(int i=1;i<=q;i++) {
int opt,x,y;
scanf("%d%d%d",&opt,&x,&y);
if(opt==3) Q[i].push_back((node){x,y});
else {
s[++tot]=(query){opt,x,y,0,i};
if(opt==1) {scanf("%d",&s[tot].z);}
}
}
Build(1,1,q);
sort(s+1,s+1+tot,cmp);
for(int i=tot;i;i--) {
if(s[i].opt==1) {
if(i<tot&&s[i].x==s[i+1].x&&s[i].y==s[i+1].y) {if(s[i].t<s[i+1].t)Update(1,s[i].t,s[i+1].t-1,i);else continue;}
else {Update(1,s[i].t,q,i);}
}
}
for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1,xos[i]=we[i]=0;
solve(1);
for(int i=1;i<=q;i++)if(Q[i].size())printf("%d\n",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)