来个抽象点的做法。
首先显然可以将条件转化成,将 中的边从大到小加入一个图中,找出加入哪条边后不是一个二分图。显然可以用一个拓展域并查集维护。
观察到朴素暴力是 ,几乎已经能过了(其实就是能过)。于是考虑进行一些小的处理,把它变成实际上就是能过的。
再观察,发现 也是相对小的,考虑利用这个性质, 小说明可能可以 合并两个并查集,于是尝试预处理一些并查集再合并。
因为每次肯定是从大往小加边,于是考虑先按照边权从小到大排序。发现大概 次操作是可以接受的,所以值域上每 分一块。
对于每一块内,我们想要快速判断,当前的并查集再并上这个区间内的所有编号 的边后,是否还满足是一个二分图。
于是考虑对每一块开一棵线段树,线段树上每个节点都是一个并查集,存储编号区间 且边权属于这个块内的所有边加入一个并查集的结果。
对于每一次询问 ,从后往前检查每一个块。每次尝试加入这块内 的所有边。这在线段树上是 个区间,找出这些区间并把所有并查集合并。再检查此时是否还是一个二分图。若不是,则将并查集回退到这次操作前,暴力尝试加入该块内的所有边。否则检查下一个块。
这样的时间复杂度,设块长为 ,是 的,在 取 时理论上可过。但是有个大问题,就是空间是 显然爆炸。
解决这个问题可以考虑,其实我们并不关心每条边编号的具体位置,只关心它们是否在一个询问区间内。于是将所有 离线下来离散化,初始化每个块内的线段树时只用判断当前编号属于哪个区间就行了。
于是空间复杂度变成 ,时间 。换个 short 就过了。
另外,作者在写这篇题解的时候突然发现,如果把线段树换成猫树可以做到 ,似乎会快很多。可能会补一个,也有可能咕咕咕了。
code:
#define L(i) ((i)*B+1)
#define R(i) min(((i)+1)*B,m)
bool Mbe;
int n,m,q,k,B=1e5+44,id[M],ls[Q<<1];
struct node{
int u,v,w,id;
}a[M],b[M];
struct Node{
int l,r;
}d[Q];
struct DSU{
short fa[N<<1];
void init(){
rep(i,1,n+n){
fa[i]=i;
}
}
int fd(int x){
return fa[x]==x?x:fa[x]=fd(fa[x]);
}
il void mrg(int x,int y){
fa[fd(x)]=fd(y);
}
};
struct SGT{
DSU tr[Q<<3];
void bld(int l,int r,int u){
tr[u].init();
if(l==r){
return;
}
int mid=(l+r)>>1;
bld(l,mid,u<<1),bld(mid+1,r,u<<1|1);
}
void upd(int l,int r,int u,int x,int y){
tr[u].mrg(a[y].u,a[y].v+n);
tr[u].mrg(a[y].u+n,a[y].v);
if(l==r){
return;
}
int mid=(l+r)>>1;
if(x<=mid){
upd(l,mid,u<<1,x,y);
}else{
upd(mid+1,r,u<<1|1,x,y);
}
}
void qry(int l,int r,int u,int x,int y,DSU &D){
if(r<x||l>y){
return;
}
if(l>=x&&r<=y){
rep(i,1,n+n){
D.mrg(i,tr[u].fd(i));
}
return;
}
int mid=(l+r)>>1;
qry(l,mid,u<<1,x,y,D),qry(mid+1,r,u<<1|1,x,y,D);
}
}T[6];
il bool cmp(node x,node y){
return x.w<y.w;
}
void Yorushika(){
read(n,m,q);
rep(i,1,m){
read(a[i].u,a[i].v,a[i].w);
a[i].id=i,b[i]=a[i];
}
sort(b+1,b+m+1,cmp);
rep(i,1,m){
id[b[i].id]=(i-1)/B;
}
rep(i,1,q){
read(d[i].l,d[i].r);
ls[i+i-1]=d[i].l,ls[i+i]=d[i].r+1;
}
sort(ls+1,ls+q+q+1);
k=unique(ls+1,ls+q+q+1)-ls-1;
rep(i,0,(m-1)/B){
T[i].bld(1,k,1);
}
rep(i,1,m){
int p=upper_bound(ls+1,ls+k+1,i)-ls-1;
T[id[i]].upd(1,k,1,p,i);
}
rep(i,1,q){
DSU x;x.init();
int p=-1,l=lower_bound(ls+1,ls+k+1,d[i].l)-ls,r=lower_bound(ls+1,ls+k+1,d[i].r+1)-ls;
drep(j,(m-1)/B,0){
DSU tmp=x;
T[j].qry(1,k,1,l,r-1,x);
rep(k,1,n){
if(x.fd(k)==x.fd(k+n)){
p=j,x=tmp;
break;
}
}
if(~p){
break;
}
}
if(p==-1){
puts("-1");
continue;
}
drep(j,R(p),L(p)){
if(b[j].id<d[i].l||b[j].id>d[i].r){
continue;
}
if(x.fd(b[j].u)==x.fd(b[j].v)){
printf("%d\n",b[j].w);
break;
}
x.mrg(b[j].u,b[j].v+n);
x.mrg(b[j].u+n,b[j].v);
}
}
}
bool Med;
signed main(){
cerr<<(&Mbe-&Med)/1048576.0<<'\n';
int t=1;
//read(t);
while(t--){
Yorushika();
}
}