本萌萌哒弱菜出了一题(其实思路是集训队论文给的),但~算法不是很优美,求各位神犇去虐一虐~~~
提交地址
http://www.lydsy.com/JudgeOnline/problem.php?id=4234
测试数据
测试数据: http://pan.baidu.com/s/1qWDV9la 密码: c7nj
命题报告:http://pan.baidu.com/s/1o6qtgJC (写的很傻逼,神犇轻D)
如果有了更优的算法,一定记得告诉本弱菜一声哦~~~
代码什么的
写的很长,因为前面有2k的输入输出优化……
lgg语句是debug语句
具体实现和命题报告里的有一些差别
//pb_ds NOI template 20150710
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cassert>
#include <cmath>
#include <vector>
#include <set>
#include <utility>
#include <queue>
#define For(i, a, b) for(register int i = a, ___u = b; i <= ___u; ++i)
#define ForDown(i, a, b) for(register int i = b, ___d = a; i >= ___d; --i)
#define cmax(i, j) ((i) < (j) ? (i) = (j) : (i))
#define cmin(i, j) ((i) > (j) ? (i) = (j) : (i))
#define dmax(i, j) ((i) > (j) ? (i) : (j))
#define dmin(i, j) ((i) < (j) ? (i) : (j))
#define ddel(i, j) ((i) > (j) ? (i) - (j) : (j) - (i))
#include <queue>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/tree_policy.hpp>
namespace io
{
const int MAXBUF = 1 << 18;
char B[MAXBUF], *S = B, *T = B;
#define getc() (S == T && (T = (S = B) + fread(B, 1, MAXBUF, stdin), S == T) ? 0 : *S++)
inline int F()
{
register int ch, aa = 0, bb = 0;
register char *S = io::S, *T = io::T;
for(ch = getc(); (ch < '0' || ch > '9') && ch != '-'; ch = getc())
;
for(ch == '-' ? bb = 1 : aa = ch - '0', ch = getc(); '0' <= ch && ch <= '9'; ch = getc())
aa += (aa << 3) + aa + ch - '0';
io::S = S, io::T = T;
return bb ? -aa : aa;
}
inline double Ff()
{
register double aa, bb;
register char ch;
register char *S = io::S, *T = io::T;
while(ch=getc(),(ch<'0'||ch>'9'))
;aa=ch-'0';
while(ch=getc(),(ch>='0'&&ch<='9'))aa=aa*10+ch-'0';
if(ch=='.'){bb=1;while(ch=getc(),ch>='0'&&ch<='9')bb*=0.1,aa+=bb*(ch-'0');}
io::S = S, io::T = T;
return aa;
}
char buff[MAXBUF], *iter = buff;
template<class T>inline void P(register T x, register char ch = '\n')
{
static int stack[110];
register int O = 0;
register char *iter = io::iter;
if(!x)*iter++ = '0';
else
{
(x < 0) ? x = -x, *iter++ = '-' : 1;
for(; x; x /= 10)
stack[++O] = x % 10;
for(; O; *iter++ = '0' + stack[O--])
;
}
*iter++ = ch, io::iter = iter;
}
inline int gets(register char *o)
{
register char *s = o, ch = getc();
for(; ch && (ch == ' ' || ch == '\n'); ch = getc())
;
for(; ch && (ch != ' ' && ch != '\n'); ch = getc())
*s++ = ch;
*s = 0;
return s - o;
}
inline void output() {fwrite(buff, 1, iter - buff, stdout);}
}
#include <ext/pb_ds/priority_queue.hpp>
namespace pb_ds
{
using io::F;
using io::P;
#define RG register
int n;
const int MAXN = 200010, MAXM = 400010;
namespace lct
{
const int MAXN = pb_ds::MAXN << 1;
int tot;
int fa[MAXN], son[MAXN][2], time[MAXN], cho[MAXN];
bool rev[MAXN], mark[MAXN], have[MAXN];
#define type(i) (son[fa[i]][1] == (i))
#define not_root(i) (son[fa[i]][type(i)] == (i))
inline void push_up(register int i)
{
static int A, B;
have[i] = have[son[i][0]] || mark[i] || have[son[i][1]];
time[i] < time[cho[i] = ((time[A = cho[son[i][0]]] < time[B = cho[son[i][1]]]) ? A : B)]
? cho[i] = i : 1;
///*lgg*/assert(time[cho[i]] <= time[i] && time[cho[i]] <= time[cho[son[i][0]]] && time[cho[i]] <= time[cho[son[i][1]]]);
}
inline void push_down(register int i)
{
if(rev[i])
{
rev[i] = 0, rev[son[i][0]] ^= 1, rev[son[i][1]] ^= 1;
register int t = son[i][0]; son[i][0] = son[i][1], son[i][1] = t;
}
}
inline void rotate(register int i)
{
register int f = fa[i], t = type(i);
fa[i] = fa[f], not_root(f) ? son[fa[f]][type(f)] = i : 1;
(son[f][t] = son[i][!t]) ? fa[son[f][t]] = f : 1;
push_up(son[fa[f] = i][!t] = f);
}
inline void preview(register int i)
{
if(not_root(i)) preview(fa[i]);
push_down(i);
}
inline void splay(register int i, register bool need = 1)
{
if(need) preview(i);
for( ; not_root(i); rotate(i))
if(not_root(fa[i])) rotate(type(i) ^ type(fa[i]) ? i : fa[i]);
push_up(i);
}
inline void dfs_print(register int i)
{
if(!i)return;
dfs_print(son[i][0]);
printf("%d ", i);
dfs_print(son[i][1]);
}
inline void debug(register int root)
{
splay(root);
printf("root = %d chain = ", root);
dfs_print(root);
puts("");
}
inline int access(register int i)
{
register int j = 0;
for( ; i; splay(i), son[i][1] = j, j = i, i = fa[i])
;
return j;
}
inline int query(RG int x, RG int y) {return access(x), access(y);}
inline void make_root(register int i) {access(i), splay(i, 0), rev[i] ^= 1;}
inline void link(register int i, register int j)
{
///*lgg*/printf("link %d ~ %d\n", i, j);
make_root(i), fa[i] = j;
///*lgg*///printf("linked "); debug(j);
}
inline void cut(register int i, register int j)
{
make_root(i), access(j), splay(i, 0), son[i][1] = fa[j] = 0;
///*lgg*/ assert(son[i][1] == j);
///*lgg*/// puts("cut"); printf("i: "); debug(i); printf("j: "); debug(j);
}
inline int find_root(register int i)
{
for(access(i), splay(i, 0); son[i][0]; i = son[i][0])
;
return i;
}
inline int expose(register int i, register int j)
{
if(i == j) return j;
make_root(i), access(j), splay(j, 0);
return j;
}
inline void set_mark(RG int i, RG bool b)
{
splay(i), mark[i] = b, push_up(i);
}
}
namespace graph
{
int fir[MAXN], tot = 1, next[MAXM], to[MAXM];
inline void reset() {memset(fir, 0, sizeof fir); tot = 1;}
inline void link(RG int x, RG int y)
{
next[++tot] = fir[x], to[fir[x] = tot] = y;
next[++tot] = fir[y], to[fir[y] = tot] = x;
}
}
namespace segment
{
const int MAXNODE = 10000000;
const int LL = 1, RR = 1000000;
int tot, lef[MAXNODE], rig[MAXNODE], size[MAXNODE];
inline int insert(RG int val, RG int old, RG int l = LL, RG int r = RR)
{
RG int at = ++tot;
size[at] = size[old] + 1;
///*lgg*/if(l==LL&&r==RR)printf("insert val = %d at = %d l = %d r = %d size = %d\n", val, at, l, r, size[at]);
if(l < r)
{
RG int m = (l + r) >> 1;
(val <= m)
? (lef[at] = insert(val, lef[old], l, m), rig[at] = rig[old])
: (lef[at] = lef[old], rig[at] = insert(val, rig[old], m + 1, r));
///*lgg*/assert(size[at] == size[lef[at]] + size[rig[at]]);
}
return at;
}
}
int val[MAXN];
struct E {int x, y;} e[MAXN];
int root[MAXN], top[MAXN], fa[MAXN], dep[MAXN] = {0, 1};
bool chosen[MAXN], vis[MAXN];
inline int dfs_init(RG int at)
{
///*lgg*///printf("at = %d fa = %d\n", at, fa[at]);
using namespace graph;
root[at] = segment::insert(val[at], root[fa[at]]);
vis[at] = 1;
RG int size = 1, cho = 0, max_cho = 0, d = dep[at] + 1, temp;
for(RG int i = fir[at]; i; i = next[i])
!vis[to[i]]
? fa[to[i]] = at, dep[to[i]] = d,
size += (temp = dfs_init(to[i])),
temp > max_cho ? cho = to[i], max_cho = temp : 1 : 1;
chosen[cho] = 1;
///*lgg*///printf("dfs_init at = %d val = %d dep = %d size = %d cho = %d\n", at, val[at], dep[at], size, cho);
return size;
}
inline void dfs_make(RG int at)
{
///*lgg*/printf("at = %d fa = %d\n", at, fa[at]);
using namespace graph;
vis[at] = 0,
top[at] = (chosen[at] ? top[fa[at]] : at);
///*lgg*///printf("at = %d top = %d\n", at, top[at]);
for(RG int i = fir[at]; i; i = next[i])
if(vis[to[i]]) dfs_make(to[i]);
}
inline int lca(RG int x, RG int y)
{
while(top[x] != top[y])
dep[top[x]] > dep[top[y]]
? x = fa[top[x]] : y = fa[top[y]];
return dep[x] < dep[y] ? x : y;
}
struct Change {int at, val, cnt; } change[MAXN];
struct Segment {int root, cnt; } seg[MAXN];
int change_cnt, seg_cnt;
int marked[MAXN], marked_cnt;
namespace lct
{
inline void dfs(RG int at)
{
if(!have[at]) return;
push_down(at);
dfs(son[at][0]);
///*lgg*///printf("at = %d\n", at);
if(mark[at])
{
///*lgg*/printf("found mark %d\n", at);
marked[++marked_cnt] = at;
}
dfs(son[at][1]);
}
}
inline void build()
{
RG int x, y;
graph::reset();
segment::tot = change_cnt = 0;
memset(chosen, 0, sizeof chosen);
For(i, 1, n)
if(lct::mark[i]) lct::set_mark(i, 0);
For(i, n + 1, n + n - 1)
{
graph::link(x = e[i].x, y = e[i].y);
if(lct::mark[i])
lct::set_mark(i, 0);
///*lgg*/assert(!lct::mark[i]);
///*lgg*/printf("link %d ~ %d time = %d\n", x, y, lct::time[i]+(1<<30));
}
///*lgg*/For(i,0,n*2)assert(!lct::mark[i]);
fa[1] = 0;
dfs_init(1);
dfs_make(1);
}
inline void main()
{
n = F();
RG int q = F(), H = 2 * sqrt(n), timer = -1 << 30;
For(i, 1, n) val[i] = F();
RG int x, y;
For(i, n + 1, n + n - 1)
{
e[i] = (E) {x = F(), y = F()};
lct::time[i] = ++timer;
lct::link(x, i);
lct::link(i, y);
}
build();
RG int k, modify_tot = 0, cho;
///*lgg*/printf("H = %d\n", H);
For(aaaa, 1, q)
{
k = F(), x = F(), y = F();
///*lgg*/if(k==-2)build();else
if(k == -1)
{
cho = lct::cho[lct::expose(x, y)];
lct::cut(e[cho].x, cho);
lct::cut(cho, e[cho].y);
///*lgg*/printf("replace %d (%d ~ %d) time = %d with (%d ~ %d) time = %d\n", cho, e[cho].x, e[cho].y,lct::time[cho]+(1<<30),x,y,timer+1+(1<<30));
e[cho] = (E) {x, y};
lct::time[cho] = ++timer;
lct::mark[cho] = lct::mark[x] = lct::mark[y] = 1;
lct::link(x, cho);
lct::link(cho, y);
if(!(++modify_tot % H))
build();
lct::expose(x, y);
///*lgg*///lct::debug(lct::expose(x,y));
}
else if(!k)
{
change[++change_cnt] = (Change) {x, val[x], -1};
///*lgg*/printf("change at = %d cnt[%d] -1 cnt[%d] +1\n", x,val[x],y);
change[++change_cnt] = (Change) {x, val[x] = y, 1};
if(!(++modify_tot % H))
build();
}
else
{
///*lgg*/printf("query %d %d\n", x, y);
if(x == y)
{
P(val[x]);
continue;
}
seg_cnt = marked_cnt = 0;
if(!lct::mark[x]) marked[++marked_cnt] = x;
lct::dfs(lct::expose(x, y));
if(!lct::mark[y]) marked[++marked_cnt] = y;
//现在是处理mark的点的时候
marked[++marked_cnt] = MAXN;
RG int a, b, c;
For(i, 1, marked_cnt)
{
a = marked[i];
while(marked[i] <= n) ++i;
b = marked[i - 1];
if(a == b)
{
seg[++seg_cnt] = (Segment) {root[a], 1};
if(fa[a])seg[++seg_cnt] = (Segment) {root[fa[a]], -1};
///*lgg*/printf("add_point %d fa = %d\n", a, fa[a]);
}
else
{
c = lca(a, b);
seg[++seg_cnt] = (Segment) {root[a], 1};
seg[++seg_cnt] = (Segment) {root[b], 1};
seg[++seg_cnt] = (Segment) {root[c], -1};
if(fa[c])seg[++seg_cnt] = (Segment) {root[fa[c]], -1};
///*lgg*/printf("add_chain %d ~ %d lca = %d flca = %d\n", a, b, c, fa[c]);
}
}
static int temp[2][MAXN];
RG int *f = temp[0], *g = temp[1], *t, l = segment::LL, r = segment::RR, left, m;
f[0] = 0, lct::make_root(x);
For(i, 1, change_cnt)
if(lct::query(y, change[i].at) == change[i].at)
f[++f[0]] = i;
///*lgg*/For(i, 1,seg_cnt)printf("root = %d cnt = %d size = %d\n", seg[i].root, seg[i].cnt, segment::size[seg[i].root]);
while(l < r)
{
///*lgg*/printf("l = %d r = %d k = %d m = %d\n", l, r, k, (l+r)/2);
///*lgg*/For(i,1,f[0])printf("assoc change at = %d val = %d cnt = %d\n", change[f[i]].at, change[f[i]].val, change[f[i]].cnt);
left = 0;
m = (l + r) >> 1;
For(i, 1, seg_cnt)
left += segment::size[segment::lef[seg[i].root]] * seg[i].cnt;
///*lgg*/printf("segment left = %d\n", left);
For(i, 1, f[0])
if(change[f[i]].val <= m)
left += change[f[i]].cnt;
///*lgg*/printf("segment + change left = %d\n", left);
if(k <= left)
{
r = m;
For(i, 1, seg_cnt)
seg[i].root = segment::lef[seg[i].root];
g[0] = 0;
For(i, 1, f[0])
if(change[f[i]].val <= m)
g[++g[0]] = f[i];
}
else
{
l = m + 1;
k -= left;
For(i, 1, seg_cnt)
seg[i].root = segment::rig[seg[i].root];
g[0] = 0;
For(i, 1, f[0])
if(m < change[f[i]].val)
g[++g[0]] = f[i];
}
t = g, g = f, f = t;
///*lgg*/getchar();
}
///*lgg*/printf("ans = %d\n", l);
P(l);
}
//if(!(modify_tot % H)) fprintf(stderr, "rebuild i = %d\n", aaaa);
}
io::output();
}
}
int main()
{
pb_ds::main();
}