调了好久啊,果然不是这错一点就是那错一点……
我们可以把题目倒过来做,时间倒流,删边变成加边,对于每个查询(u,v),抓出来一条链记录最大值即可
对于每个加入(u,v),先是找到u,v边上的最大值,如果当前u,v<_max,那么删去最大值那条边,加入u,v
代码写得很丑,BZOJ上过不了,反正自己测过了~
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
const int INF = 1000001;
const int MAXN = 100001;
const int MAXM = 1000001;
const int MAXQ = 100001;
void READ(int &x)
{
char c;
x = 0;
do c = getchar();while (c > '9' || c < '0');
do x = x*10+c-48, c = getchar();while (c >= '0' && c <= '9');
}
struct Ques
{
int oper,u,v,dist,id;
};
int n,m,q;
int f[2*MAXN];
Ques Q[MAXQ];
int ans[MAXQ];
struct Edge
{
bool flag;
int u,v,dist,id;
bool operator < (const Edge &rhs) const
{
return u < rhs.u || (u == rhs.u && v < rhs.v);
}
Edge(int _u,int _v,int _dist,int _id):u(_u),v(_v),dist(_dist),id(_id){}
Edge(){}
};
bool cmp1(Edge A,Edge B)
{
return A.dist < B.dist;
}
bool cmp2(Edge A,Edge B)
{
return A.id < B.id;
}
Edge Edges[2*MAXM];
struct Node *null;
struct Node
{
int flag;
int id;
int dist,size;
int _max,maxlocal;
Node *ch[2],*f;
int d(){return f->ch[1] == this ? 1 : 0;}
bool check(){return f != null && (f->ch[0] == this || f->ch[1] == this);}
void setc(Node *c,int d){ch[d] = c, c->f = this;}
Node(int _dist):dist(_dist){size = 1, f = ch[0] = ch[1] = null, flag = false;}
Node(){size = 0, dist = _max = -INF, f = ch[0] = ch[1] = NULL, flag = false;}
void maintain()
{
size = 1+ch[0]->size+ch[1]->size;
maxlocal = id,
_max = dist;
if (ch[0]->_max > _max) maxlocal = ch[0]->maxlocal,_max = ch[0]->_max;
if (ch[1]->_max > _max) maxlocal = ch[1]->maxlocal,_max = ch[1]->_max;
}
void pushdown()
{
if (flag)
{
flag = false;
ch[0]->flag ^= 1, ch[1]->flag ^= 1;
swap(ch[0],ch[1]);
}
}
};
Node *p[MAXM*2];
void rotate(Node *p)
{
Node *x = p->f;
x->pushdown();p->pushdown();
int d = p->d();
if (!x->check()) p->f = x->f;
else x->f->setc(p,x->d());
x->setc(p->ch[d^1],d);
p->setc(x,d^1);
x->maintain();
}
void Splay(Node *p)
{
p->pushdown();
while (p->check())
{
Node *x = p->f;
if (!x->check()) rotate(p);
else x->d() == p->d() ? (rotate(x),rotate(p)) : (rotate(p),rotate(p));
}
p->maintain();
}
void Access(Node *p)
{
for (Node *q = null; p != null; p = p->f)
{
Splay(p);
p->setc(q,1);
(q = p)->maintain();
}
}
void MakeRoot(Node *p)
{
Access(p);Splay(p);
p->flag ^= 1;
}
void Link(Node *p,Node *q)
{
MakeRoot(p);
p->f = q;
}
void Cut(Node *p,Node *q)
{
MakeRoot(p);
Access(q);Splay(q);
q->ch[0] = p->f = null;
q->maintain();
}
Node* Query(Node *p,Node *q)
{
MakeRoot(p);
Access(q);Splay(q);
return q;
}
int find(int x)
{
return x == f[x] ? f[x] : f[x] = find(f[x]);
}
int main()
{
null = new Node();
READ(n);READ(m);READ(q);
for (int i=1;i<=2*m;i++) p[i] = new Node(0), p[i]->id = i;
for (int i=1;i<=m;i++)
{
READ(Edges[i].u),READ(Edges[i].v),READ(Edges[i].dist);
if (Edges[i].u > Edges[i].v) swap(Edges[i].u,Edges[i].v);
}
sort(Edges+1,Edges+m+1,cmp1);
for (int i=1;i<=m;i++) Edges[i].id = i;
sort(Edges+1,Edges+m+1);
for (int i=1;i<=q;i++)
{
READ(Q[i].oper),READ(Q[i].u),READ(Q[i].v);
if (Q[i].u > Q[i].v) swap(Q[i].u,Q[i].v);
if (Q[i].oper == 1) continue;
int temp = lower_bound(Edges+1,Edges+m+1,(Edge){Q[i].u,Q[i].v,0,0})-Edges;
Edges[temp].flag = true;
Q[i].dist = Edges[temp].dist;
Q[i].id = Edges[temp].id;
}
sort(Edges+1,Edges+m+1,cmp2);
for (int i=1;i<=2*m;i++) f[i] = i;
int cnt = 0;
for (int i=1;i<=m;i++) if (!Edges[i].flag)
{
int Su = find(Edges[i].u);
int Sv = find(Edges[i].v);
if (Su == Sv) continue;
f[Su] = Sv;
p[i+n]->dist = Edges[i].dist;
Link(p[Edges[i].u],p[i+n]);Link(p[Edges[i].v],p[i+n]);
cnt++;
if (cnt == n-1) break;
}
for (int i=q;i>0;i--)
{
if (Q[i].oper == 1) ans[i] = Query(p[Q[i].u],p[Q[i].v])->_max;
else
{
Node *temp = Query(p[Q[i].u],p[Q[i].v]);
if (Q[i].dist < temp->_max)
{
int point = temp->maxlocal-n;
Cut(p[point+n],p[Edges[point].u]);Cut(p[point+n],p[Edges[point].v]);
point = Q[i].id;
p[point+n]->dist = Q[i].dist;
Link(p[point+n],p[Edges[point].u]);Link(p[point+n],p[Edges[point].v]);
}
}
}
for (int i=1;i<=q;i++) if (Q[i].oper == 1) printf("%d\n",ans[i]);
return 0;
}