Link
先转化为最小割。
显然\(A\rightarrow A,B\rightarrow B\)的边最多割一条。
那么如果我们割的是\(A_u\rightarrow A_{u+1},B_{v-1}\rightarrow B_v\),那么总共的代价是\(\sum\limits_{i=1}^u\sum\limits_{j=v}^ne(i,j)+e(A_u,A_{u+1})+e(B_{v-1},B_v)\)。
最开始的情况我们可以用线段树对每一个\(u\)计算出最优的\(v\)。
之后修改只会修改\(e(A_u,A_{u+1})\)这一部分,所以对每个\(u\),最优的\(v\)是不会变的,用树状数组/线段树搞搞就完事了。
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<utility>
#define pi pair<int,int>
#define fi first
#define se second
using std::vector;
using std::pair;
using ll=long long;
const int N=200007;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
ll min(ll a,ll b){return a<b? a:b;}
vector<pi>e[N];ll a[N],b[N],c[N],mn[N<<2],tag[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
void pushup(int p){mn[p]=min(mn[ls],mn[rs]);}
void modify(int p,ll v){mn[p]+=v,tag[p]+=v;}
void pushdown(int p){if(!tag[p])return;modify(ls,tag[p]),modify(rs,tag[p]),tag[p]=0;}
void build(int p,int l,int r)
{
if(l==r) return (void)(mn[p]=b[l]);
build(ls,l,mid),build(rs,mid+1,r),pushup(p);
}
void update(int p,int l,int r,int L,int R,int x)
{
if(R<l||r<L) return ;
if(L<=l&&r<=R) return modify(p,x);
pushdown(p),update(ls,l,mid,L,R,x),update(rs,mid+1,r,L,R,x),pushup(p);
}
#undef ls
#undef rs
#undef mid
int main()
{
int n=read(),m=read(),q=read();
for(int i=1;i<n;++i) a[i]=read(),b[i+1]=read();
for(int i=1,u,v,w;i<=m;++i) u=read(),v=read(),w=read(),e[u].emplace_back(v,w);
build(1,1,n);
for(int u=1;u<=n;c[u++]=mn[1]) for(auto[v,w]:e[u]) update(1,1,n,1,v,w);
memset(tag+1,0,n<<5),memset(mn+1,0,n<<5);
for(int i=1;i<=n;++i) b[i]=a[i]+c[i];
build(1,1,n),printf("%I64d\n",mn[1]);
for(int u,w;q;--q) u=read(),w=read(),update(1,1,n,u,u,w-a[u]),a[u]=w,printf("%I64d\n",mn[1]);
}