省选联测26

A.排列

发现最大值的最小值一定是找到最高同时出现01的位,按01分组,各选一个异或的最小值,在所有能异或出这个值的数之间连边,那么就是要么选一个同组的数,要么选一个和自己有连边的数,判一下合法贪心选最小即可。

点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=4e5+10;

struct Trie{
	int son[maxn*30][2],tot=1;
	void Insert(int x){
		int u=1;
		Dwn(i,30,0){
			int c=(x>>i)&1;
			if(!son[u][c])son[u][c]=++tot;
			u=son[u][c];
		}
	}
	int Min(int x){
		int u=1,res=0;
		Dwn(i,30,0){
			int c=(x>>i)&1;
			if(son[u][c])u=son[u][c];
			else u=son[u][c^1],res|=(1<<i);
		}
		return res;
	}
}T;

int n,a[maxn];
int Maxi,ans=INT_MAX;
map<int,int>Map;
vector<int>vec[maxn];
set<int>S[2];int sum[2];
int bel[maxn],b[maxn],to[maxn],Ans[maxn];

bool Check(int x){
	if(vec[x].size()>=2)return true;
	int t=(b[x]>>Maxi)&1;
	if(S[t].size()==1 || S[t^1].empty())return true;
	return sum[t^1]-(!vec[to[x]].empty())>0;
}
void Del(int i){
	int x=a[i],t=bel[i];
	S[t].erase(i);vec[x].pop_back();
	if(vec[x].empty()){
		int tmp=(!vec[to[x]].empty());
		sum[t]-=tmp,sum[t^1]-=tmp;
	}
}

void solve(){
	cin>>n;Rep(i,1,n)cin>>a[i];
	Dwn(j,30,0){
		int cnt=0;
		Rep(i,1,n)cnt+=(a[i]>>j)&1;
		if(cnt > 0 && cnt<n){ Maxi=j;break; }
		if(cnt)Rep(i,1,n)a[i]^=(1<<j);
	}
	Dwn(i,n,1){
		if(!Map[a[i]])Map[a[i]]=Map.size();
		vec[Map[a[i]]].emplace_back(i);
	}
	Rep(i,1,n)if(!((a[i]>>Maxi)&1))T.Insert(a[i]),S[0].insert(i);
	Rep(i,1,n)if((a[i]>>Maxi)&1)ans=min(ans,T.Min(a[i])),S[1].insert(i),bel[i]=1;
	Rep(i,1,n){
		b[Map[a[i]]]=a[i];
		a[i]=Map[a[i]];
		to[a[i]]=Map[ans^b[a[i]]];
		if(vec[a[i]].back()==i)sum[bel[i]]+=(to[a[i]]!=0);
	}
	Rep(i,1,n)if(Check(a[i])){ Del(i); Ans[1]=i; break; }
	Rep(i,2,n){
		int x=a[Ans[i-1]],t=bel[Ans[i-1]];
		int X=n+1,Y=n+1;
		for(auto it : S[t])
			if(Check(a[it])){ X=it;break; }
		if(!vec[to[x]].empty() && Check(a[vec[to[x]].back()]))Y=vec[to[x]].back();
		X=min(X,Y);
		Del(X),Ans[i]=X;
	}Rep(i,1,n)cout<<Ans[i]<<" ";
}

int main (){ fre(roast);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

B.王

赛时写的是对的,但是暴力写挂了,于是我TM没交!!

我的做法非常暴力,设\(f_{i,j,0-7}\),就是答案的贡献形式是\(Xabc\)的形式,\(X\)始终存在,最后一维八个值是\(abc\)存在的所有组合的dp值的和。
那么转移就很简单了,举两个例子。

  • 假设接下来走的这步与上一步方向相同,且走到一个红色列
    则新贡献为\(X(a+1)b(c+1) = Xacb + Xbc +Xab + Xb\)
  • 假设接下来走的这步与上一步方向不同
    此时combo的次数要重新计算了,而我们所定义的dp中的\(c\)实际是当前的combo次数,由于之后的操作不会影响到前面的贡献,于是我们可以把之前的\(c\)等效为\(X\),具体的就是把同向转移粘过来,把\((c+1)\)的贡献去掉,然后看等号右侧的每一项,如果没有\(c\)就给它加上\(c\)就行了,实现可以看代码,考场写的,全手写的转移。
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define int ll
using namespace std;

const int maxn=2e3+10,Mod=998244353;

ll f[maxn][maxn][3][8];
// 0 :: left up  --  1 :: straight up  -- 2 :: right up
//[0] = all           //	Xabc
//[1] = except a      // 	Xbc
//[2] = except b      // 	Xac
//[3] = except c      // 	Xab
//[4] = except ac     // 	Xb
//[5] = except bc     // 	Xa
//[6] = except ab     //	Xc
//[7] = except abc    //    X
//
//
// all = X*a*b*c

int n,m;char s[maxn];int a[maxn][maxn];
function<int(int)>To[3];
struct FUNC_INIT{
	FUNC_INIT(){
		To[0]=[&](const int &x){ return (x-1)<0 ? x-1+m : x-1; };
		To[1]=[&](const int &x){ return x; };
		To[2]=[&](const int &x){ return (x+1)>=m ? x+1-m : x+1; };
	}
}Func_I;

ll Xabc(ll *t){ return t[0]; }
ll Xbc(ll *t){ return t[1]; }
ll Xac(ll *t){ return t[2]; }
ll Xab(ll *t){ return t[3]; }
ll Xb(ll *t){ return t[4]; }
ll Xa(ll *t){ return t[5]; }
ll Xc(ll *t){ return t[6]; }
ll X(ll *t){ return t[7]; }

void solve(){
	cin>>n>>m>>s;swap(n,m);
	Rep(i,1,n)Rep(j,0,m-1)cin>>a[i][j];
	for(int j=0;j<m;++j){
		Rep(t,0,2){
			int p=To[t](j);
			f[2][p][t][0]=(f[2][p][t][0]+1LL*a[1][j]*(3-(s[j]!='r')-(s[p]!='r'))*(3-(s[j]!='b')-(s[p]!='b')))%Mod;
			f[2][p][t][1]=(f[2][p][t][1]+1LL*a[1][j]*(3-(s[j]!='b')-(s[p]!='b'))%Mod);
			f[2][p][t][2]=(f[2][p][t][2]+1LL*a[1][j]*(3-(s[j]!='r')-(s[p]!='r'))%Mod);
			f[2][p][t][3]=(f[2][p][t][3]+1LL*a[1][j]*(3-(s[j]!='r')-(s[p]!='r'))*(3-(s[j]!='b')-(s[p]!='b')))%Mod;
			f[2][p][t][4]=(f[2][p][t][4]+1LL*a[1][j]*(3-(s[j]!='b')-(s[p]!='b'))%Mod);
			f[2][p][t][5]=(f[2][p][t][5]+1LL*a[1][j]*(3-(s[j]!='r')-(s[p]!='r'))%Mod);
			f[2][p][t][6]=(f[2][p][t][6]+1LL*a[1][j])%Mod;
			f[2][p][t][7]=(f[2][p][t][7]+1LL*a[1][j])%Mod;
		}
	}
	for(int i=2;i<n;++i)for(int j=0;j<m;++j)Rep(k,0,2){
		Rep(l,0,7)f[i][j][k][l]=f[i][j][k][l]*a[i][j]%Mod;
		Rep(t,0,2){
			int p=To[t](j);
			ll *now=f[i][j][k],*tar=f[i+1][p][t];
			if(t==k){
				if(s[p]=='r'){
					tar[0]=(tar[0]+Xabc(now)+Xbc(now)+Xab(now)+Xb(now))%Mod;
					tar[1]=(tar[1]+Xbc(now)+Xb(now))%Mod;
					tar[2]=(tar[2]+Xac(now)+Xa(now)+Xc(now)+X(now))%Mod;
					tar[3]=(tar[3]+Xab(now)+Xb(now))%Mod;
					tar[4]=(tar[4]+Xb(now))%Mod;
					tar[5]=(tar[5]+Xa(now)+X(now))%Mod;
					tar[6]=(tar[6]+Xc(now)+X(now))%Mod;
					tar[7]=(tar[7]+X(now))%Mod;
				}
				if(s[p]=='b'){
					tar[0]=(tar[0]+Xabc(now)+Xac(now)+Xab(now)+Xa(now))%Mod;
					tar[1]=(tar[1]+Xbc(now)+Xb(now)+Xc(now)+X(now))%Mod;
					tar[2]=(tar[2]+Xac(now)+Xa(now))%Mod;
					tar[3]=(tar[3]+Xab(now)+Xa(now))%Mod;
					tar[4]=(tar[4]+Xb(now)+X(now))%Mod;
					tar[5]=(tar[5]+Xa(now))%Mod;
					tar[6]=(tar[6]+Xc(now)+X(now))%Mod;
					tar[7]=(tar[7]+X(now))%Mod;
				}
				if(s[p]=='w'){
					tar[0]=(tar[0]+Xabc(now)+Xab(now))%Mod;
					tar[1]=(tar[1]+Xbc(now)+Xb(now))%Mod;
					tar[2]=(tar[2]+Xac(now)+Xa(now))%Mod;
					tar[3]=(tar[3]+Xab(now))%Mod;
					tar[4]=(tar[4]+Xb(now))%Mod;
					tar[5]=(tar[5]+Xa(now))%Mod;
					tar[6]=(tar[6]+Xc(now)+X(now))%Mod;
					tar[7]=(tar[7]+X(now))%Mod;
					
				}
			}else{
				if(s[p]=='r'){
					tar[0]=(tar[0]+Xabc(now)+Xbc(now))%Mod;
					tar[1]=(tar[1]+Xbc(now))%Mod;
					tar[2]=(tar[2]+Xac(now)+Xc(now))%Mod;
					tar[3]=(tar[3]+Xabc(now)+Xbc(now))%Mod;
					tar[4]=(tar[4]+Xbc(now))%Mod;
					tar[5]=(tar[5]+Xac(now)+Xc(now))%Mod;
					tar[6]=(tar[6]+Xc(now))%Mod;
					tar[7]=(tar[7]+Xc(now))%Mod;
				}
				if(s[p]=='b'){
					tar[0]=(tar[0]+Xabc(now)+Xac(now))%Mod;
					tar[1]=(tar[1]+Xbc(now)+Xc(now))%Mod;
					tar[2]=(tar[2]+Xac(now))%Mod;
					tar[3]=(tar[3]+Xabc(now)+Xac(now))%Mod;
					tar[4]=(tar[4]+Xbc(now)+Xc(now))%Mod;
					tar[5]=(tar[5]+Xac(now))%Mod;
					tar[6]=(tar[6]+Xc(now))%Mod;
					tar[7]=(tar[7]+Xc(now))%Mod;
				}
				if(s[p]=='w'){
					tar[0]=(tar[0]+Xabc(now))%Mod;
					tar[1]=(tar[1]+Xbc(now))%Mod;
					tar[2]=(tar[2]+Xac(now))%Mod;
					tar[3]=(tar[3]+Xabc(now))%Mod;
					tar[4]=(tar[4]+Xbc(now))%Mod;
					tar[5]=(tar[5]+Xac(now))%Mod;
					tar[6]=(tar[6]+Xc(now))%Mod;
					tar[7]=(tar[7]+Xc(now))%Mod;
				}

			}
		}
	}
	ll ans=0;
	Rep(t,0,0){
		ans=0;
		for(int j=0;j<m;++j)Rep(k,0,2)ans=(ans+f[n][j][k][t]*a[n][j])%Mod;
		cout<<ans<<"\n";
	}
}

#undef int
int main (){ fre(king);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

C.铲雪

一会儿再写

点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define lowbit(x) (x&-x)
using namespace std;

namespace Mine_code{// bei ka chang
#define int ll

const int maxn=2e5+10;

mt19937 mt((ull)&maxn);
int Mtrand(int l,int r){return uniform_int_distribution<ll>(l,r)(mt);}

int n,q,rk[maxn];
int w[maxn],value[maxn];
unordered_map<int,int>Map[maxn];
ll ans;

struct BIT{
	int c[maxn];
	void Add(int x,int d){ for(;x<=n;x+=lowbit(x))c[x]+=d; }
	int Query(int x){ int res=0;for(;x;x-=lowbit(x))res+=c[x]; return res; }
}B[2];

void REMAKE(int x);

struct Seg{
	struct Tree{ int mini,sum,lazy; }tr[maxn<<2];
	void Pushup(int rt){
		tr[rt].mini=min(tr[rt<<1].mini,tr[rt<<1|1].mini),
		tr[rt].sum=(tr[rt<<1].sum+tr[rt<<1|1].sum);
	}
	void Update(int rt,int w){ tr[rt].mini+=w,tr[rt].lazy+=w; }
	void Pushdown(int rt){ if(tr[rt].lazy)Update(rt<<1,tr[rt].lazy),Update(rt<<1|1,tr[rt].lazy),tr[rt].lazy=0; }
	void Set(int rt,int l,int r,int x,int w,int c){
		if(l==r)return tr[rt].mini=w,tr[rt].sum=c,void();
		int mid=(l+r)>>1;Pushdown(rt);
		if(x<=mid)Set(rt<<1,l,mid,x,w,c);
		else Set(rt<<1|1,mid+1,r,x,w,c);
		Pushup(rt);
	}
	int Min(int rt,int l,int r,int s,int t){
		if(s<=l && t>=r)return tr[rt].mini;
		int mid=(l+r)>>1,res=INT_MAX;Pushdown(rt);
		if(s<=mid)res=min(res,Min(rt<<1,l,mid,s,t));
		if(t>mid)res=min(res,Min(rt<<1|1,mid+1,r,s,t));
		return res;
	}
	void Modify(int rt,int l,int r,int s,int t,int w){
		if(s<=l && t>=r)return Update(rt,w);
		int mid=(l+r)>>1;Pushdown(rt);
		if(s<=mid)Modify(rt<<1,l,mid,s,t,w);
		if(t>mid)Modify(rt<<1|1,mid+1,r,s,t,w);
		Pushup(rt);
	}
	int Query(int rt,int l,int r,int s,int t){
		if(s<=l && t>=r)return tr[rt].sum;
		int mid=(l+r)>>1,res=0;Pushdown(rt);
		if(s<=mid)res=Query(rt<<1,l,mid,s,t);
		if(t>mid)res+=Query(rt<<1|1,mid+1,r,s,t);
		return res;
	}
	void Reset(int rt,int l,int r,int s,int t,int val){
		if(tr[rt].mini>val)return;
		if(l>t || r<s)return;
		if(l==r)return REMAKE(rk[l]);
		int mid=(l+r)>>1;Pushdown(rt);
		if(tr[rt<<1].mini<=val)Reset(rt<<1,l,mid,s,t,val);
		if(tr[rt<<1|1].mini<=val)Reset(rt<<1|1,mid+1,r,s,t,val);
		Pushup(rt);
	}
	void Delete(int rt,int l,int r,int x){
		if(l==r)return ans-=tr[rt].mini*tr[rt].sum,tr[rt].mini=INT_MAX,tr[rt].sum=0,ans-=value[rk[l]],value[rk[l]]=0,void();
		int mid=(l+r)>>1;Pushdown(rt);
		if(x<=mid)Delete(rt<<1,l,mid,x);
		else Delete(rt<<1|1,mid+1,r,x);
		Pushup(rt);
	}
}T;

struct Graph{
	struct eg{ int from,to,next;int dis; }e[maxn*2];
	int len,head[maxn];
	void lqx(int from,int to,int dis)
	{ e[++len].from=from,e[len].to=to,e[len].next=head[from],head[from]=len;e[len].dis=dis; }
	int fa[maxn],siz[maxn],dep[maxn],son[maxn],top[maxn],dfn[maxn],Te,sum[maxn],oth[maxn];
	void Dfs1(int u){
		siz[u]=1,dep[u]=dep[fa[u]]+1;
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;if(v==fa[u])continue;
			fa[v]=u;Dfs1(v);siz[u]+=siz[v];
			if(!son[u] || siz[v]>siz[son[u]])son[u]=v;
		}
	}
	void Dfs2(int u,int tp){
		top[u]=tp;dfn[u]=++Te;rk[Te]=u;
		if(son[u])Dfs2(son[u],tp);
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;Map[u][v]=e[i].dis;
			if(v!=son[u])oth[u]=max(oth[u],e[i].dis);
			if(v==fa[u] || v==son[u])continue;
			Dfs2(v,v);
		}
	}
	void PreWork(int u){
		pii maxi(0,0);
		for(int i=head[u];i;i=e[i].next){ sum[u]+=e[i].dis; maxi=max(maxi,pii(e[i].dis,e[i].to)); }
		ans+=(sum[u]&1)*w[u];
		value[u]+=(sum[u]&1)*w[u];
		T.Set(1,1,n,dfn[u],INT_MAX,0);
		if(maxi.fir*2>sum[u]){
			ans-=(sum[u]&1)*w[u];ans+=(maxi.fir*2-sum[u])*w[u];
			value[u]=(maxi.fir*2-sum[u])*w[u];
			if(maxi.sec != fa[u] && maxi.sec != son[u])
				T.Set(1,1,n,dfn[u],2*maxi.fir-sum[u],w[u]),value[u]=0;
		}
	}
	void PRE(){ Rep(i,1,n)PreWork(i); }
	void Remake(int u){
		T.Delete(1,1,n,dfn[u]);
		pii it=max(pii(oth[u],-1),pii(Map[u][son[u]]+B[1].Query(dfn[u]),son[u]));
		if(fa[u])it=max(it,pii(top[u]==u ? Map[u][fa[u]] : Map[fa[u]][u] +B[1].Query(dfn[fa[u]]),fa[u]));
		int su=sum[u]+B[0].Query(dfn[u]);
		ans+=(su&1)*w[u];value[u]=(su&1)*w[u];
		if(it.fir*2>su){
			ans-=(su&1)*w[u];ans+=(it.fir*2-su)*w[u];
			value[u]=(it.fir*2-su)*w[u];
			if(it.sec != fa[u] && it.sec != son[u])
				T.Set(1,1,n,dfn[u],2*it.fir-su,w[u]),value[u]=0;
		}
	}
	void Add(int u,int v,int w){ Map[u][v]+=w;oth[u]=max(Map[u][v],oth[u]); }
	void Modify(int u,int v,int val){
		if(u==v)return;
		int x=u,y=v;sum[u]-=val,sum[v]-=val;
		while(top[u]!=top[v]){
			if(dep[top[u]]<dep[top[v]])swap(u,v);
			if(u != top[u]){
				B[0].Add(dfn[top[u]],2*val),B[0].Add(dfn[u]+1,-2*val);
				B[1].Add(dfn[top[u]],val),B[1].Add(dfn[u],-val);
				Add(u,fa[u],val),Add(top[u],fa[top[u]],val),Add(fa[top[u]],top[u],val);
				Remake(u),Remake(top[u]);
				if(dfn[top[u]]+1<dfn[u]){
					T.Reset(1,1,n,dfn[top[u]]+1,dfn[u]-1,2*val);
					ans-=T.Query(1,1,n,dfn[top[u]]+1,dfn[u]-1)*2*val;
					T.Modify(1,1,n,dfn[top[u]]+1,dfn[u]-1,-2*val);
				}
			}else{
				B[0].Add(dfn[top[u]],2*val),B[0].Add(dfn[u]+1,-2*val);
				B[1].Add(dfn[top[u]],val),B[1].Add(dfn[u],-val);
				Add(top[u],fa[top[u]],val),Add(fa[top[u]],top[u],val);
				Remake(top[u]);
			}
			u=fa[top[u]];
		}
		if(dep[u]>dep[v])swap(u,v);
		B[0].Add(dfn[u],2*val),B[0].Add(dfn[v]+1,-2*val);
		B[1].Add(dfn[u],val),B[1].Add(dfn[v],-val);
		if(v!=u)Add(v,fa[v],val);
		Remake(u);
		if(v!=u)Remake(v);
		if(dfn[u]+1<dfn[v]){
			T.Reset(1,1,n,dfn[u]+1,dfn[v]-1,2*val);
			ans-=T.Query(1,1,n,dfn[u]+1,dfn[v]-1)*2*val;
			T.Modify(1,1,n,dfn[u]+1,dfn[v]-1,-2*val);
		}
	}
}G;

void REMAKE(int x){ G.Remake(x); }

void solve(){
	cin>>n>>q;Rep(i,1,n)cin>>w[i];
	Rep(i,2,n){ int x,y,w;cin>>x>>y>>w;G.lqx(x,y,w),G.lqx(y,x,w); }
	int root=Mtrand(1,n);
	G.Dfs1(root),G.Dfs2(root,root);G.PRE();
	cout<<ans<<"\n";
	while(q--){
		int x,y,w;cin>>x>>y>>w;
		G.Modify(x,y,w);
		cout<<ans<<"\n";
	}
}

#undef int
int main (){ fre(snow);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }
}
#define int ll

const int N = 2e5 + 10, INF = LLONG_MAX >> 1;

mt19937 mt( ( ull )(&N) );
int Rand ( int l, int r ) { return uniform_int_distribution<int>(l,r)(mt); }

int n, m, A[N], idfn[N], S[N], V[N], res; vector < pair<int,int> > E[N];

struct Opt { int u, v, d; } O[N];

namespace T
{

int res, S[N], F[N];

int Query ( int u, int d, int a = -1, int b = -1 )
{
	int res = - max( 2 * F[u] - S[u], S[u] & 1 ) * A[u];
	S[u] = S[u] + ( a >= 0 ) * d + ( b >= 0 ) * d, F[u] = max( { F[u], a + d, b + d } ), res += max( 2 * F[u] - S[u], S[u] & 1 ) * A[u]; return res;
}

int dep[N], fa[N], val[N];

void Dfs ( int u, int f )
{
	dep[u] = dep[f] + 1, fa[u] = f;
	for( auto it : E[u] ) if( it.first != f ) val[ it.first ] = it.second, Dfs( it.first, u );
}

void Solve ()
{
	for( int u = 1; u <= n; ++u )
	{
		for( auto it : E[u] ) S[u] += it.second, F[u] = max( F[u], it.second ); res += max( 2 * F[u] - S[u], S[u] & 1 ) * A[u];
	}
	cout << res << "\n";
	Dfs( 1, 0 );
	for( int i = 1; i <= m; ++i )
	{
		int u = O[i].u, v = O[i].v, d = O[i].d, su = -1, sv = -1;
		while( u != v )
		{
			if( dep[u] > dep[v] ) res += Query( u, d, val[u], su ), su = val[u], val[u] += d, u = fa[u];
			else                  res += Query( v, d, val[v], sv ), sv = val[v], val[v] += d, v = fa[v];
		}
		res += Query( u, d, su, sv );
		cout << res << "\n";
	}
}

}

struct Data
{
	struct Ver { int val, laz, siz; } V[N<<2];

	void Pushup ( int p ) { V[p].val = min( V[p<<1].val, V[p<<1|1].val ), V[p].siz = V[p<<1].siz + V[p<<1|1].siz; }

	void Updval ( int p, int d ) { V[p].val += d, V[p].laz += d; }

	void Pushdown ( int p ) { if( V[p].laz ) Updval( p<<1, V[p].laz ), Updval( p<<1|1, V[p].laz ), V[p].laz = 0; }

	void Modify ( int p, int l, int r, int x, int y, int d )
	{
		if( x > y ) return;
		if( x <= l && r <= y ) return Updval( p, d ), void();
		Pushdown(p);
		int mid = l + ( r - l >> 1 );
		if( x <= mid ) Modify( p<<1, l, mid, x, y, d ); if( y > mid ) Modify( p<<1|1, mid+1, r, x, y, d );
		Pushup(p);
	}

	void Update ( int p, int l, int r, int x, int d )
	{
		if( l == r ) return V[p].val = d, V[p].siz = ( d != INF ? A[ idfn[l] ] : 0 ), void();
		Pushdown(p);
		int mid = l + ( r - l >> 1 );
		if( x <= mid ) Update( p<<1, l, mid, x, d ); else Update( p<<1|1, mid+1, r, x, d );
		Pushup(p);
	}

	int Find ( int p, int l, int r )
	{
		if( l == r ) return l;
		Pushdown(p);
		int mid = l +( r - l >> 1 );
		if( V[p<<1].val <= 0 ) return Find( p<<1, l, mid ); else return Find( p<<1|1, mid+1, r );
	}

	int Query ( int p, int l, int r, int x, int y )
	{
		if( x > y ) return 0;
		if( x <= l && r <= y ) return V[p].siz;
		Pushdown(p);
		int mid = l + ( r - l >> 1 ), res = 0;
		if( x <= mid ) res += Query( p<<1, l, mid, x, y ); if( y > mid ) res += Query( p<<1|1, mid+1, r, x, y );
		return res;
	}

	int Query ( int p, int l, int r, int x )
	{
		if( x <  l || x > r ) return 0;
		if( l == r ) return V[p].val;
		Pushdown(p);
		int mid = l + ( r - l >> 1 );
		if( x <= mid ) return Query( p<<1, l, mid, x ); else return Query( p<<1|1, mid+1, r, x );
	}

}D, G, U;

int fa[N], dep[N], siz[N], son[N], top[N], dfn[N], w, val[N], sonval[N], edg[N], pos[N];

void Dfs1 ( int u, int f )
{
	fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
	for( auto [ v, d ] : E[u] ) if( v != f ) { edg[v] = d, Dfs1( v, u ), siz[u] += siz[v]; if( siz[ son[u] ] < siz[v] ) son[u] = v, sonval[u] = d, val[v] = d; }
}

void Dfs2 ( int u, int t )
{
	top[u] = t, dfn[u] = ++w, idfn[w] = u;
	if( son[u] ) Dfs2( son[u], t );
	for( auto [ v, d ] : E[u] ) if( v != fa[u] && v != son[u] ) Dfs2( v, v );
}

void Update ( int u, int v )
{
	if( v == 0 ) return;
	int x = G.Query( 1, 1, n, dfn[v] ); S[u] = U.Query( 1, 1, n, dfn[u] ), V[u] = G.Query( 1, 1, n, dfn[ pos[u] ] );

	if( x > V[u] ) V[u] = x, pos[u] = v;
}

void Add ( int u, int v )
{
	if( v == 0 )
	{
		res -= max( S[u] & 1, 2 * V[u] - S[u] ) * A[u];
	}
	else
	{
		res += max( S[u] & 1, 2 * V[u] - S[u] ) * A[u];
		if( 2 * V[u] - S[u] >  0 && V[u] != G.Query( 1, 1, n, dfn[u] ) && V[u] != G.Query( 1, 1, n, dfn[ son[u] ] ) )
			 D.Update( 1, 1, n, dfn[u], 2 * V[u] - S[u] );
		else D.Update( 1, 1, n, dfn[u], INF );
	}
}

vector <int> vec;

void Solve ()
{
	cin >> n >> m;
	for( int i = 1; i <= n; ++i ) cin >> A[i];
	for( int i = 2; i <= n; ++i ) { int u, v, d; cin >> u >> v >> d, E[u].emplace_back( v, d ), E[v].emplace_back( u, d ); }
	for( int i = 1; i <= m; ++i ) cin >> O[i].u >> O[i].v >> O[i].d;

	Dfs1( 1, 0 ), Dfs2( 1, 1 );

	for( int u = 1; u <= n; ++u )
	{
		for( auto [ v, d ] : E[u] ) { S[u] += d; if( V[u] < d ) V[u] = d, pos[u] = ( v == fa[u] ? u : v ); }
		G.Update( 1, 1, n, dfn[u],  edg[u] );
		U.Update( 1, 1, n, dfn[u],    S[u] );

		res += max( S[u] & 1, 2 * V[u] - S[u] ) * A[u];

		if( 2 * V[u] - S[u] > 0 && V[u] != val[u] && V[u] != sonval[u] ) D.Update( 1, 1, n, dfn[u], 2 * V[u] - S[u] ); else D.Update( 1, 1, n, dfn[u], INF );
	}

	vec.push_back( res );

	for( int i = 1; i <= m; ++i )
	{
		int u = O[i].u, v = O[i].v, d = O[i].d;

		{
			int x = u, y = v, tx = top[x], ty = top[y];

			while( tx != ty )
			{
				if( dep[tx] < dep[ty] ) swap( tx, ty ), swap( x, y );

				Update( x, son[x] ), Update( x, x ), Add( x, 0 ); if( x != tx ) Update( tx, son[tx] ), Update( tx, tx ), Add( tx, 0 );

				x = fa[tx], tx = top[x];
			}

			if( dep[x] > dep[y] ) swap( x, y );

			Update( x, son[x] ), Update( x, x ), Add( x, 0 ); if( x != y ) Update( y, son[y] ), Update( y, y ), Add( y, 0 );
		}
//		cerr << res << endl;
		{
			int x = u, y = v, tx = top[x], ty = top[y];

			while( tx != ty )
			{
				if( dep[tx] < dep[ty] ) swap( tx, ty ), swap( x, y );

				G.Modify( 1, 1, n, dfn[tx], dfn[x], d );

				if(  x == u ||  x == v ) U.Modify( 1, 1, n, dfn[ x], dfn[ x], d ); else U.Modify( 1, 1, n, dfn[ x], dfn[ x], 2 * d );
				if( tx != x )
				if( tx == u || tx == v ) U.Modify( 1, 1, n, dfn[tx], dfn[tx], d ); else U.Modify( 1, 1, n, dfn[tx], dfn[tx], 2 * d );

				U.Modify( 1, 1, n, dfn[tx] + 1, dfn[x] - 1, 2 * d );

				Update( x, son[x] ), Update( x, x ), Add( x, 1 ); if( x != tx ) Update( tx, son[tx] ), Update( tx, tx ), Add( tx, 1 );

				D.Modify( 1, 1, n, dfn[tx] + 1, dfn[x] - 1, -2 * d );

				while( D.V[1].val <= 0 )
				{
					int p = idfn[ D.Find( 1, 1, n ) ]; res -= ( D.Query( 1, 1, n, dfn[p] ) + 2 * d ) * A[p], Update( p, son[p] ), Update( p, p ), Add( p, 1 );
				}

				res -= 2 * d * D.Query( 1, 1, n, dfn[tx] + 1, dfn[x] - 1 );

				Update( fa[tx], tx );

				x = fa[tx], tx = top[x];

				cerr << clock() * 1.0 / CLOCKS_PER_SEC << endl;
				if( clock() * 1.0 / CLOCKS_PER_SEC >= 3.3 ) return T::Solve();
			}

			if( dep[x] > dep[y] ) swap( x, y );

			G.Modify( 1, 1, n, dfn[x] + 1, dfn[y], d );

			if( x == u || x == v ) U.Modify( 1, 1, n, dfn[x], dfn[x], d ); else U.Modify( 1, 1, n, dfn[x], dfn[x], 2 * d );
			if( x != y )
			if( y == u || y == v ) U.Modify( 1, 1, n, dfn[y], dfn[y], d ); else U.Modify( 1, 1, n, dfn[y], dfn[y], 2 * d );

			U.Modify( 1, 1, n, dfn[x] + 1, dfn[y] - 1, 2 * d );

			Update( x, son[x] ), Update( x, x ), Add( x, 1 ); if( x != y ) Update( y, son[y] ), Update( y, y ), Add( y, 1 );

			D.Modify( 1, 1, n, dfn[x] + 1, dfn[y] - 1, -2 * d );

			while( D.V[1].val <= 0 )
			{
				int p = idfn[ D.Find( 1, 1, n ) ]; res -= ( D.Query( 1, 1, n, dfn[p] ) + 2 * d ) * A[p], Update( p, son[p] ), Update( p, p ), Add( p, 1 );
			}

			Update( fa[x], x );

			res -= 2 * d * D.Query( 1, 1, n, dfn[x] + 1, dfn[y] - 1 );
		}
		vec.push_back( res );
	}

	for( auto it : vec ) cout << it << "\n";
}

signed main ()
{
	fre(snow);
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); Solve(); return 0;
}

posted @ 2023-02-10 07:01  Delov  阅读(17)  评论(0编辑  收藏  举报