【模板】数据结构

数据结构

  • 权值 BIT 上二分
struct {
    int n,t[N];
	void add(int i,int x) { for(;i<=n;i+=i&-i)t[i]+=x; }
	int sum(int l,int r) {
		int res=0; for(--l;r>l;r-=r&-r)res+=t[r];
		for(;l>r;l-=l&-l)res-=t[l]; return res;
	}
	int kth(int k) {
		int p = 0;
        rFor(i,__lg(n),0) if( p+(1<<i) < n && k > t[p+(1<<i)] ) p += 1<<i, k -= t[p];
		return p+1;
	}
} ;
  • zkw 线段树

区间加,区间和

int tn;
LL t[N*4],add[N*4];
void bld() {
	tn = 1 << __lg(n+1)+1;
	For(i,1,n) t[tn+i] = a[i];
	rFor(i,tn-1,1) t[i] = t[i<<1] + t[i<<1|1];
}
void mdf(int l,int r,LL x) {
	int sizl = 0, sizr = 0, len = 1;
	for(l = tn+l-1, r = tn+r+1; l^r^1; l/=2, r/=2, len*=2) {
		t[l] += x*sizl, t[r] += x*sizr;
		if( ~l & 1 ) add[l^1] += x, t[l^1] += x*len, sizl += len;
		if( r & 1 ) add[r^1] += x, t[r^1] += x*len, sizr += len;
	}
	for(; l; l/=2, r/=2) t[l] += x*sizl, t[r] += x*sizr;
}
LL qry(int l,int r) {
	int sizl = 0, sizr = 0, len = 1; LL res = 0;
	for(l = tn+l-1, r = tn+r+1; l^r^1; l/=2, r/=2, len*=2) {
		res += add[l]*sizl + add[r]*sizr;
		if( ~l & 1 ) res += t[l^1], sizl += len;
		if( r & 1 ) res += t[r^1], sizr += len;
	}
	for(; l; l/=2, r/=2) res += add[l]*sizl + add[r]*sizr;
	return res;
}
  • 权值线段树合并,分裂
#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
#define mid (l+r>>1)
int ind,bin[N];
struct { int ch[2]; LL siz; } t[N*];
void delnode(int u) { t[u] = {0,0,0}, bin[++bin[0]] = u; }
int newnode() { return bin[0] ? bin[bin[0]--] : ++ind; }
void up(int u) { t[u].siz = t[ls(u)].siz + t[rs(u)].siz; }
int merge(int u,int v) {
	if( !u || !v ) return u | v;
	ls(u) = merge(ls(u),ls(v)), rs(u) = merge(rs(u),rs(v)), t[u].siz += t[v].siz;
	return delnode(v), u;
}
void split(int ql,int qr,int &u,int &v,int l=,int r=) {
	if( !u || qr < l || r < ql ) return;
	if( ql <= l && r <= qr ) { v = u, u = 0; return; }
	v = newnode();
	split(ql,qr,ls(u),ls(v),l,mid), split(ql,qr,rs(u),rs(v),mid+1,r);
	t[v].siz = t[ls(v)].siz + t[rs(v)].siz, t[u].siz -= t[v].siz;
}
  • 李超线段树

区间插入,区间 min

#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct LC {
	int t[N*4]; LL k[N],b[N],mn[N*4];
	LC() { memset(mn,0x3f,sizeof mn); }
	LL f(int i,int x) { return k[i] * x + b[i]; }
	void mdf(int ql,int qr,int i,int u=1,int l=1,int r=n) {
		if( qr < l || r < ql ) return;
		if( ql <= l && r <= qr ) {
			ckmin(mn[u], min(f(i,l),f(i,r)));
			if( !t[u] ) { t[u] = i; return; }
			if( f(i,mid) < f(t[u],mid) ) swap(i,t[u]);
			if( f(i,l) < f(t[u],l) ) mdf(ql,qr,i,ls,l,mid);
			else if( f(i,r) < f(t[u],r) ) mdf(ql,qr,i,rs,mid+1,r);
			return;
		}
		mdf(ql,qr,i,ls,l,mid), mdf(ql,qr,i,rs,mid+1,r);
		ckmin(mn[u], min(mn[ls],mn[rs]));
	}
	LL qry(int ql,int qr,int u=1,int l=1,int r=n) {
		if( r < ql || qr < l ) return 1e18;
		if( ql <= l && r <= qr ) return mn[u];
		LL res = infl;
		if( t[u] ) res = min(f(t[u],max(ql,l)), f(t[u],min(qr,r)));
		return min({res, qry(ql,qr,ls,l,mid), qry(ql,qr,rs,mid+1,r)});
	}
} lc;

全局插入,单点 min,合并。复杂度 O(nlogV)

#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
#define mid (l+r>>1)
int rt[N];
struct LC {
	int ind; LL k[N],b[N];
	struct Node { int ch[2],id; } t[N*30];
	LL f(int i,int x) { return k[i] * x + b[i]; }
	void mdf(int i,int &u,int l=-1e5,int r=1e5) {
		if( !u ) u = ++ind;
		if( !t[u].id ) { t[u].id = i; return; }
		if( f(i,mid) < f(t[u].id,mid) ) swap(i,t[u].id);
		if( f(i,l) < f(t[u].id,l) ) mdf(i,ls(u),l,mid);
		else if( f(i,r) < f(t[u].id,r) ) mdf(i,rs(u),mid+1,r);
	}
	void ins(LL x,LL y,int &u) { k[++k[0]] = x, b[k[0]] = y, mdf(k[0],u); }
	LL qry(int x,int u,int l=-1e5,int r=1e5) {
		if( !u ) return 1e18;
		if( l == r ) return f(t[u].id,x);
		return min(f(t[u].id,x), x<=mid?qry(x,ls(u),l,mid):qry(x,rs(u),mid+1,r));
	}
	int merge(int u,int v,int l=-1e5,int r=1e5) {
		if( !u || !v ) return u | v;
		if( l == r ) return f(t[u].id,l)<f(t[v].id,l) ? u : v;
		ls(u) = merge(ls(u),ls(v),l,mid), rs(u) = merge(rs(u),rs(v),mid+1,r);
		return mdf(t[v].id,u,l,r), u;
	}
} lc;
  • 可持久化 01Trie

值域 [0,230)

struct {
	int ind,rt[N],ch[N*31][2],siz[N*31];
	void ins(int u,int v,int s) {
		u = rt[u], v = rt[v] = ++ind;
		rFor(i,29,0) {
			bool c = s>>i&1;
			ch[v][!c] = ch[u][!c], u = ch[u][c], v = ch[v][c] = ++ind,
			siz[v] = siz[u] + 1;
		}
	}
	int qry(int u,int v,int s) {
		u = rt[u], v = rt[v];
		int res = 0;
		for(int i = 1<<29; i; i >>= 1) {
			bool c = ~s&i;
			if( siz[ch[u][c]] < siz[ch[v][c]] ) res |= i, u = ch[u][c], v = ch[v][c];
			else u = ch[u][!c], v = ch[v][!c];
		}
		return res;
	}
} ;
  • 笛卡尔树

升序 BST 以 i 为权值,小根堆以 a[i] 为权值

void bld() {
	For(i,1,n) {
		int tmp = tp;
		while( tp && a[i] < a[stk[tp]] ) --tp;
		if( tp ) ch[stk[tp]][1] = i;
		if( tp < tmp ) ch[i][0] = stk[tp+1];
		stk[++tp] = i;
	}
}
  • 可持久化文艺平衡树

空间限制 256MB

// LG5586 [P5350] 序列 (加强版)
#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
const int N = 3e5+5, M = 5e6;
int ind,rt,n,a[N],len[N];
struct Node { int ch[2],siz,len; mint val,sum,add; bool rev; } t[M+N];
int node(int len,mint x)
	{ return t[++ind] = {0,0,len,len,x,len*x,0,0}, ind; }
int node(const Node &x){ return t[++ind] = x, ind; }
void up(int u) {
	t[u].siz = t[ls(u)].siz + t[rs(u)].siz + t[u].len,
	t[u].sum = t[ls(u)].sum + t[rs(u)].sum + t[u].len*t[u].val;
}
void down(int u,mint x,bool y) {
	if( x.x ) t[u].val += x, t[u].add += x, t[u].sum += t[u].siz * x;
	if( y ) t[u].rev ^= y, swap(ls(u),rs(u));
}
void down(int u) { if( t[u].add.x || t[u].rev ) {
	if( ls(u) ) down( ls(u)=node(t[ls(u)]) ,t[u].add,t[u].rev);
	if( rs(u) ) down( rs(u)=node(t[rs(u)]) ,t[u].add,t[u].rev);
	t[u].add = t[u].rev = 0;
}}
void dfs(int u) {
	down(u);
	if( ls(u) ) dfs(ls(u));
	if( n && a[n] == t[u].val.x ) len[n] += t[u].len;
	else a[++n] = t[u].val.x, len[n] = t[u].len;
	if( rs(u) ) dfs(rs(u));
}
int bld(int l=1,int r=n) {
	if( l > r ) return 0;
	int mid = l+r>>1, u = node(len[mid],a[mid]);
	return ls(u) = bld(l,mid-1), rs(u) = bld(mid+1,r), up(u), u;
}
void rbld() { n = 0, dfs(rt), ind = 0, rt = bld(); }
void split(int u,int k,int &l,int &r) {
	if( !u ) { l = r = 0; return; }
	down(u);
	if( t[ls(u)].siz < k && k < t[ls(u)].siz+t[u].len ) {
		int mid = k-t[ls(u)].siz, v = node(t[u]);
		t[v].len = t[u].len-mid, t[u].len = mid;
		ls(v) = 0, rs(u) = v, up(v), up(u);
	}
	if( k <= t[ls(u)].siz ) r = node(t[u]), split(ls(r),k,l,ls(r)), up(r);
	else l = node(t[u]), split(rs(l),k-t[ls(l)].siz-t[l].len,rs(l),r), up(l);
}
int merge(int l,int r) {
	if( !l || !r ) return l | r;
	int u;
	if( mt()%(t[l].siz+t[r].siz) < t[l].siz )
		down(u=node(t[l])), rs(u) = merge(rs(u),r);
	else down(u=node(t[r])), ls(u) = merge(l,ls(u));
	return up(u), u;
}
mint sum(int l,int r) { // ask sum of [l,r]
	int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
	mint res = t[b].sum;
	rt = merge(merge(a,b),c);
	return res;
}
void cov(int l,int r,int x) { // let [l,r] = x
	int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
	rt = merge(merge(a,node(r-l+1,x)),c);
}
void add(int l,int r,int x) { // let [l,r] += x
	int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
	down(b,x,0);
	rt = merge(merge(a,b),c);
}
void copy(int l1,int r1,int l2,int r2) { // let [l2,r2] = [l1,r1]
	int a,b,c,d,e; bool flg = 0;
	if( l1 > l2 ) swap(l1,l2), swap(r1,r2), flg = 1;
	split(rt,r2,d,e), split(d,l2-1,c,d), split(c,r1,b,c), split(b,l1-1,a,b);
	rt = merge(merge(merge(merge(a,!flg?b:d),c),!flg?b:d),e);
}
void swap(int l1,int r1,int l2,int r2) { // swap [l1,r1] and [l2,r2]
	if( l1 > l2 ) swap(l1,l2), swap(r1,r2);
	int a,b,c,d,e;
	split(rt,r2,d,e), split(d,l2-1,c,d), split(c,r1,b,c), split(b,l1-1,a,b);
	rt = merge(merge(merge(merge(a,d),c),b),e);
}
void rev(int l,int r) { // reverse [l,r]
	int a,b,c; split(rt,r,b,c), split(b,l-1,a,b);
	down(b,0,1);
	rt = merge(merge(a,b),c);
}
void dbg() {
	n = 0, dfs(rt);
	For(i,1,n, p = 1) {
		if( len[i] > 1 ) cerr<<"["<<p<<","<<p+len[i]-1<<"]:";
		cerr<<a[i]<<(i<n?' ':'\n');
		p += len[i];
	}
}
signed main() {
	cin>>n>>m; For(i,1,n) cin>>a[i], len[i] = 1;
	rt = bld();
	while( m-- ) {
		
		if( ind >= M ) rbld();
//		dbg();
	}
	n = 0, dfs(rt); For(i,1,n) For(j,1,len[i]) cout<<a[i]<<" ";
}
  • 珂朵莉树
struct CT {
	int l,r;
	mutable int val;
	CT(int l=0,int r=0,int val=0):l(l),r(r),val(val){}
	bool operator < (const CT &rhs) const { return l < rhs.l; }
}; set<CT> ct;
auto split(int p) {
	auto it = --ct.upper_bound({p});
	if( it->l == p ) return it;
	int l = it->l, r = it->r, x = it->val;
	ct.erase(it), ct.emplace(l,p-1,x);
	return ct.emplace(p,r,x).fi;
}
void assign(int l,int r,int x) {
	auto itr = split(r+1), itl = split(l);
	// if( itr != ct.end() && x == itr->val ) r = (itr++)->r;
	// if( itl != ct.begin() && x == prev(itl)->val) l = (--itl)->l;
	ct.erase(itl,itr), ct.emplace(l,r,x);
}
  • KDT

  • LCT

#define ls(u) t[u].ch[0]
#define rs(u) t[u].ch[1]
struct {
	struct Node { int fa,ch[2]; bool rev; } t[];
	void rev(int u) { swap(ls(u),rs(u)), t[u].rev ^= 1; }
	void down(int u) { if( t[u].rev ) rev(ls(u)), rev(rs(u)), t[u].rev = 0; }
	bool nrt(int u) { return ls(t[u].fa)==u || rs(t[u].fa)==u; }
	bool wh(int u) { return rs(t[u].fa)==u; }
	void rtt(int x) {
		int y = t[x].fa, z = t[y].fa, k = wh(x), w = t[x].ch[!k];
		if( nrt(y) ) t[z].ch[wh(y)] = x; t[x].ch[!k] = y, t[y].ch[k] = w;
		t[w].fa = y, t[y].fa = x, t[x].fa = z;
	}
	void splay(int u) {
		static int tp,stk[N];
		for(int v = stk[tp=1] = u; nrt(v); stk[++tp] = v = t[v].fa);
		while( tp ) down(stk[tp--]);
		for(int fa; fa = t[u].fa, nrt(u); rtt(u))
			if( nrt(fa) ) rtt(wh(fa)==wh(u)?fa:u);
	}
	void acs(int x) {
		for(int u = x, v = 0; u; u = t[v=u].fa) splay(u), rs(u) = v;
		splay(x);
	}
	void mkrt(int u) { acs(u), rev(u); }
	int fdrt(int u) {
		acs(u);
		while( ls(u) ) down(u), u = ls(u);
		return splay(u), u;
	}
	void split(int u,int v) { mkrt(u), acs(v); }
	void link(int u,int v) { mkrt(u), t[u].fa = v; }
	void cut(int u,int v) { split(u,v), t[u].fa = ls(v) = 0; }
} ;
  • 压位 trie

值域 [0,220)

// bzoj3685 普通van Emde Boas树
#define ctz(x) (uLL)__builtin_ctzll(x)
#define clz(x) (uLL)__builtin_clzll(x)
struct Trie {
	uLL *t[4];
	Trie() {
		t[0] = new uLL[1<<14](), t[1] = new uLL[1<<8](),
		t[2] = new uLL[1<<2](), t[3] = new uLL[1<<0]();
	}
	void ins(int x) {
		Rep(i,0,4) {
			uLL &u = t[i][x>>(i+1)*6], e = 1ull<<(x>>i*6&63);
			if( u & e ) return; u |= e;
		}
	}
	void ers(int x)
        { Rep(i,0,4) if( t[i][x>>(i+1)*6] &= ~(1ull<<(x>>i*6&63)) ) return; }
	int min() {
		if( !t[3][0] ) return -1;
		int u = 0; rFor(i,3,0) u |= ctz(t[i][u>>(i+1)*6]) << i*6;
		return u;
	}
	int max() {
		if( !t[3][0] ) return -1;
		int u = 0; rFor(i,3,0) u |= 63-clz(t[i][u>>(i+1)*6]) << i*6;
		return u;
	}
	int suf(int x) {
		Rep(i,0,4) {
			int e = x>>i*6&63; uLL u = t[i][x>>(i+1)*6];
			if( u>>e > 1 ) {
				int res = x >> (i+1)*6 << (i+1)*6;
				res |= ctz(u>>e+1)+e+1 << i*6;
				rFor(j,i-1,0) res |= ctz(t[j][res>>(j+1)*6]) << j*6;
				return res;
			}
		}
		return -1;
	}
	int pre(int x) {
		Rep(i,0,4) {
			int e = x>>i*6&63; uLL u = t[i][x>>(i+1)*6];
			if( u & (1ull<<e)-1 ) {
				int res = x >> (i+1)*6 << (i+1)*6;
				res |= 63-clz(u&(1ull<<e)-1) << i*6;
				rFor(j,i-1,0) res |= 63-clz(t[j][res>>(j+1)*6]) << j*6;
				return res;
			}
		}
		return -1;
	}
	int qry(int x) { return t[0][x>>6] & 1ull<<(x&63) ? 1 : -1; }
} ;

  • 区间逆序对

LG5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I

  • 区间众数

LG5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III

  • 块状链表,值域分块

值域同序列长度

// LG4278 带插入区间K小值
const int N = 7e4+5, B = 512, BN = N/B+5;
struct DS { // 值域分块
	int sum[BN],cnt[N];
	void add(int x,int y) { sum[x/B] += y, cnt[x] += y; }
};
struct Blk : Vi {
	DS ds;
	void ins(int i,int x) { emplace(begin()+i,x), ds.add(x,1); }
}; vector<Blk> bk(1); // 块状链表

Pii find(int p) { // 块状链表定位 p 位置
	Rep(i,0,sz(bk))
		if( p < sz(bk[i]) ) return {i,p};
		else p -= sz(bk[i]);
	return {sz(bk)-1,sz(bk.back())};
}

void ins(int p,int x) { // p 位置前插入 x
	int i,j; tie(i,j) = find(p);
	bk[i].ins(j,x);
	Rep(k,i+1,sz(bk)) bk[k].ds.add(x,1);
	if( sz(bk[i]) > 2*B ) {
		Vi a(bk[i].end()-B,bk[i].end());
		bk[i].erase(bk[i].end()-B,bk[i].end()),
		bk.emplace(bk.begin()+i+1,Blk()), bk[i+1].ds = bk[i].ds;
		for(int k : a) bk[i].ds.add(k,-1), bk[i+1].pb(k);
	}
}
void mdf(int p,int x) { // p 位置的值改为 x
	int i,j; tie(i,j) = find(p);
	int y = bk[i][j]; bk[i][j] = x;
	Rep(k,i,sz(bk)) bk[k].ds.add(x,1), bk[k].ds.add(y,-1);
}
int qry(int l,int r,int x) { // 查询 [l,r] 第 x 小
	static DS ds;
	int li,lj,ri,rj; tie(li,lj) = find(l), tie(ri,rj) = find(r);
	auto add=[&](int y) {
		if( li == ri ) For(i,lj,rj) ds.add(bk[li][i],y);
		else {
			Rep(i,lj,sz(bk[li])) ds.add(bk[li][i],y);
			For(i,0,rj) ds.add(bk[ri][i],y);
		}
	};
	add(1);
	for(int i = 0; ; ++i) {
		int y = ds.sum[i] + (li<ri?bk[ri-1].ds.sum[i]-bk[li].ds.sum[i]:0);
		if( x > y ) x -= y;
		else {
			i = i*B-1;
			do
				++i,
				x -= ds.cnt[i] + (li<ri?bk[ri-1].ds.cnt[i]-bk[li].ds.cnt[i]:0);
			while( x > 0 );
			add(-1);
			return i;
		}
	}
}

莫队

  • 莫队二次离线

LG5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II

区间逆序对

const int N = 1e5+5, B = 313;
int n,m,a[N],in[N];
LL f[N],g[N],ans[N];
VI lsh;
struct Q { int id,l,r; } q[N];
struct Node {
	int id,op,l,r;
	Node(int a=0,int b=0,int c=0,int d=0){ id=a,op=b,l=c,r=d; }
}; vector<Node> q1[N],q2[N];

struct BIT {
	int t[N];
	void add(int i) { for(;i<=n;i+=i&-i)++t[i]; }
	int sum(int i) { int res=0;for(;i;i-=i&-i)res+=t[i];return res; }
} bit;

struct Block {
	int add[N],sum[N];
	void clr() { mem(add,0,in[n]), mem(sum,0,n); }
	void mdf(int p) {
		for(int i = p; in[i] == in[p]; ++i) ++sum[i];
		For(i,in[p]+1,in[n]) ++add[i];
	}
	int qry(int p) { return sum[p] + add[in[p]]; }
} blk;

void mo() {
	For(i,1,n) in[i] = (i+B-1)/B;
	For(i,1,m) q[i].id = i, read(q[i].l,q[i].r);
	sort(q+1,q+m+1,[](const Q &x,const Q &y)
		{return in[x.l]!=in[y.l]?x.l<y.l:in[x.l]&1?x.r<y.r:x.r>y.r;});
	For(i,1,m, l = 1, r = 0) {
		if( r < q[i].r )
			ans[q[i].id] += f[q[i].r]-f[r], q1[l-1].pb(q[i].id,-1,r+1,q[i].r),
			r = q[i].r;
		if( q[i].l < l )
			ans[q[i].id] += g[q[i].l]-g[l], q2[r+1].pb(q[i].id,-1,q[i].l,l-1),
			l = q[i].l;
		if( q[i].r < r )
			ans[q[i].id] -= f[r]-f[q[i].r], q1[l-1].pb(q[i].id,1,q[i].r+1,r),
			r = q[i].r;
		if( l < q[i].l )
			ans[q[i].id] -= g[l]-g[q[i].l], q2[r+1].pb(q[i].id,1,l,q[i].l-1),
			l = q[i].l;
	}
	For(i,1,n) {
		blk.mdf(a[i]);
		for(auto j : q1[i]) For(k,j.l,j.r) ans[j.id] += j.op * (i-blk.qry(a[k]));
	}
	blk.clr();
	rFor(i,n,1) {
		blk.mdf(a[i]);
		for(auto j : q2[i]) For(k,j.l,j.r) ans[j.id] += j.op * blk.qry(a[k]-1);
	}
	For(i,1,m) ans[q[i].id] += ans[q[i-1].id];
}

signed main() {
	read(n,m); lsh.resize(n+1), lsh[0] = -1;
	For(i,1,n) read(a[i]), lsh[i] = a[i];
	sort(all(lsh)), lsh.erase(unique(all(lsh)),lsh.end());
	For(i,1,n) a[i] = lower_bound(all(lsh),a[i])-lsh.begin();
	For(i,1,n) bit.add(a[i]), f[i] = f[i-1] + i-bit.sum(a[i]);
	mem(bit.t,0,n);
	rFor(i,n,1) bit.add(a[i]), g[i] = g[i+1] + bit.sum(a[i]-1);
	mo();
	For(i,1,m) write(ans[i]);
	return ocl();
}
  • 树上带修莫队

LG4074 [WC2013] 糖果公园

const int N = 1e5+5;
int n,m,mm,tn,qn,a[N],p[N],b[N];
LL val[N],w[N];
vector<int> e[N];
struct Q { int l,r,t,lca,id; } q[N];

int size,ind,fa[N][17],dep[N],fi[N],se[N],id[2*N],in[2*N],cnt[N];
LL now,ans[N];
bool vis[N*2];

void dfs(int u,int f) {
	fi[u] = ++ind, id[ind] = u;
	dep[u] = dep[ fa[u][0]=f ]+1;
	For(i,1,16) fa[u][i] = fa[fa[u][i-1]][i-1];
	for(int v : e[u]) if( v != f ) dfs(v,u);
	se[u] = ++ind, id[ind] = u;
}
int lca(int u,int v) {
	if( dep[u] < dep[v] ) swap(u,v);
	rFor(i,16,0) if( dep[fa[u][i]] >= dep[v] ) u = fa[u][i];
	if( u == v ) return u;
	rFor(i,16,0) if( fa[u][i] != fa[v][i] ) u = fa[u][i], v = fa[v][i];
	return fa[u][0];
}

bool operator < (const Q &x,const Q &y) {
	if( in[x.l] != in[y.l] ) return x.l<y.l;
	if( in[x.r] != in[y.r] ) return x.r<y.r;
	return x.t<y.t;
}
void add(int x) { now += val[a[x]] * w[++cnt[a[x]]]; }
void del(int x) { now -= val[a[x]] * w[cnt[a[x]]--]; }
void up(int x) {
	if( !vis[x] ) add(x);
	else del(x);
	vis[x] ^= 1;
}
void modify(int x) {
	if( vis[p[x]] ) del(p[x]);
	swap(a[p[x]],b[x]);
	if( vis[p[x]] ) add(p[x]);
}

signed main() {
	read(n,m,mm);
	For(i,1,m) read(val[i]);
	For(i,1,n) read(w[i]);
	for(int i = 1; i < n; ++i) {
		int x,y; read(x,y);
		e[x].pb(y), e[y].pb(x);
	}
	For(i,1,n) read(a[i]);
	size = pow(n,2./3);
	For(i,1,2*n) in[i] = (i-1)/size+1;
	dfs(1,0);
	For(i,1,mm) {
		int op; read(op);
		if( !op ) ++tn, read(p[tn],b[tn]);
		else {
			++qn;
			q[qn].id = qn, q[qn].t = tn;
			int x,y; read(x,y);
			if( fi[x] > fi[y] ) swap(x,y);
			int anc = lca(x,y);
			if( anc == x ) q[qn].l = fi[x], q[qn].r = fi[y];
			else q[qn].l = se[x], q[qn].r = fi[y], q[qn].lca = anc;
		}
	}
	sort(q+1,q+qn+1);
	for(int i = 1, l = 1, r = 0, t = 0; i <= qn; ++i) {
		while( r < q[i].r ) up(id[++r]);
		while( l > q[i].l ) up(id[--l]);
		while( l < q[i].l ) up(id[l++]);
		while( r > q[i].r ) up(id[r--]);
		while( t < q[i].t ) modify(++t);
		while( t > q[i].t ) modify(t--);
		if( q[i].lca ) up(q[i].lca);
		ans[q[i].id] = now;
		if( q[i].lca ) up(q[i].lca);
	}
	For(i,1,qn) write(ans[i]);
	return iocl();
}
posted @   ft61  阅读(25)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示