省选联测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;
}