标签:
1 7 3 1 2 1 3 2 4 2 5 3 6 3 7 2 3 4 4 5 3 6 7 3
6HintStack expansion program: #pragma comment(linker, "/STACK:1024000000,1024000000")
考虑dp,
容易想到有两种转移
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<vector>
#include<iomanip>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (100000+10)
#define MAXM (200000+10)
#define MAXV (1000+10)
#define pb push_back
#define mp make_pair
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef int ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
struct Chain{
int u,v,w;
Chain(){}
Chain(int _u,int _v,int _w):u(_u),v(_v),w(_w){}
};
vector<Chain> a[MAXN];
int n,m;
int edge[MAXM],Next[MAXM],Pre[MAXN],siz=1;
void addedge(int u,int v)
{
edge[++siz]=v;
Next[siz]=Pre[u];
Pre[u]=siz;
}
void addedge2(int u,int v){addedge(u,v);addedge(v,u);}
bool vis[MAXN];
int cnt,id[MAXN];
int son[MAXN],dep[MAXN],sz[MAXN],top[MAXN],pre[MAXN],q[MAXN];
void build()
{
MEM(vis) cnt=0; MEM(id)
MEM(son) MEM(dep) MEM(sz) MEM(top) MEM(pre) MEM(q)
int r=1;
vis[dep[1]=q[1]=1]=1;
For(i,r)
{
int u=q[i];
Forp(u)
{
int v=edge[p];
if (vis[v]) continue; else vis[v]=1;
dep[ q[++r]=v ]=dep[u]+1;
pre[v]=u;
}
}
ForD(i,r) {
sz[pre[q[i]]] += ++sz[q[i]];
if (sz[son[pre[q[i]]]]<sz[q[i]] ) son[pre[q[i]]] = q[i];
}
For(i,r) {
if (!top[q[i]])
for(int x=q[i];x;x=son[x]) {
top[x]=q[i];
id[x]=++cnt;
}
}
}
int lca(int a,int b)
{
while(1) {
if (top[a]==top[b]) return dep[a]<=dep[b] ? a:b;
if (dep[top[a]]<dep[top[b]]) swap(a,b);
a=pre[top[a]];
}
}
#define MEM2(a,i) memset(a,i,sizeof(a));
class SegmentTree
{
ll a[MAXN*4],minv[MAXN*4],sumv[MAXN*4],maxv[MAXN*4],addv[MAXN*4],setv[MAXN*4];
int n;
public:
SegmentTree(){MEM(a) MEM(minv) MEM(sumv) MEM(maxv) MEM(addv) MEM2(setv,-1) }
SegmentTree(int _n):n(_n){MEM(a) MEM(minv) MEM(sumv) MEM(maxv) MEM(addv) MEM2(setv,-1) }
void mem(int _n)
{
n=_n;
MEM(a) MEM(minv) MEM(sumv) MEM(maxv) MEM(addv) MEM2(setv,-1)
}
void maintain(int o,int L,int R)
{
sumv[o]=maxv[o]=minv[o]=0;
if (L<R) //只考虑左右子树
{
sumv[o]=sumv[Lson]+sumv[Rson];
minv[o]=min(minv[Lson],minv[Rson]);
maxv[o]=max(maxv[Lson],maxv[Rson]);
} //只考虑add操作
if (setv[o]>=0) sumv[o]=setv[o]*(R-L+1),minv[o]=maxv[o]=setv[o];
minv[o]+=addv[o];maxv[o]+=addv[o];sumv[o]+=addv[o]*(R-L+1);
}
int y1,y2,v;
void update(int o,int L,int R) //y1,y2,v
{
if (y1<=L&&R<=y2) {
addv[o]+=v;
}
else{
pushdown(o);
int M=(R+L)>>1;
if (y1<=M) update(Lson,L,M); else maintain(Lson,L,M);
if (M< y2) update(Rson,M+1,R); else maintain(Rson,M+1,R);
}
maintain(o,L,R);
}
void update2(int o,int L,int R)
{
if (y1<=L&&R<=y2) {
setv[o]=v;addv[o]=0;
}
else{
pushdown(o);
int M=(R+L)>>1;
if (y1<=M) update2(Lson,L,M); else maintain(Lson,L,M); //维护pushodown,再次maintain
if (M< y2) update2(Rson,M+1,R); else maintain(Rson,M+1,R);
}
maintain(o,L,R);
}
void pushdown(int o)
{
if (setv[o]>=0)
{
setv[Lson]=setv[Rson]=setv[o];
addv[Lson]=addv[Rson]=0;
setv[o]=-1;
}
if (addv[o])
{
addv[Lson]+=addv[o];
addv[Rson]+=addv[o];
addv[o]=0;
}
}
ll _min,_max,_sum;
void query2(int o,int L,int R,ll add)
{
if (setv[o]>=0)
{
_sum+=(setv[o]+addv[o]+add)*(min(R,y2)-max(L,y1)+1);
_min=min(_min,setv[o]+addv[o]+add);
_max=max(_max,setv[o]+addv[o]+add);
} else if (y1<=L&&R<=y2)
{
_sum+=sumv[o]+add*(R-L+1);
_min=min(_min,minv[o]+add);
_max=max(_max,maxv[o]+add);
} else {
// pushdown(o);
int M=(L+R)>>1;
if (y1<=M) query2(Lson,L,M,add+addv[o]);// else maintain(Lson,L,M);
if (M< y2) query2(Rson,M+1,R,add+addv[o]);// else maintain(Rson,M+1,R);
}
//maintain(o,L,R);
}
void query(int o,int L,int R,ll add) //y1,y2
{
if (y1<=L&&R<=y2)
{
_sum+=sumv[o]+add*(R-L+1);
_min=min(_min,minv[o]+add);
_max=max(_max,maxv[o]+add);
}
else{
int M=(R+L)>>1;
if (y1<=M) query(Lson,L,M,add+addv[o]);
if (M< y2) query(Rson,M+1,R,add+addv[o]);
}
}
void add(int l,int r,ll v)
{
if (l>r) swap(l,r);
y1=l,y2=r;this->v=v;
update(1,1,n);
}
void set(int l,int r,ll v)
{
y1=l,y2=r;this->v=v;
update2(1,1,n);
}
ll ask(int l,int r,int b=1)
{
if (l>r) swap(l,r);
_sum=0,_min=INF,_max=-1;
y1=l,y2=r;
query2(1,1,n,0);
switch(b)
{
case 1:return _sum;
case 2:return _min;
case 3:return _max;
default:break;
}
}
void print()
{
For(i,n)
cout<<ask(i,i,1)<<' ';
cout<<endl;
}
//先set后add
}S[2]; //sum & dp
int d[MAXN],s[MAXN];
ll Ask(int a,int b,int f)
{
ll ans=0;
while (top[a]^top[b]) {
if (dep[top[a]]<dep[top[b]]) swap(a,b);
ans+=S[f].ask(id[top[a]],id[a],1);
a=pre[top[a]];
}
if (dep[a]>dep[b]) swap(a,b);
ans+=S[f].ask(id[a],id[b],1);
return ans;
}
void dfs(int u,int fa)
{
Forp(u)
{
int v=edge[p];
if (v==fa) continue;
dfs(v,u);
s[u]+=d[v];
}
d[u]=s[u];
S[0].add(id[u],id[u],s[u]);
int tot=a[u].size();
Rep(j,tot)
{
Chain t = a[u][j];
int fee=t.w;
//
d[u]=max(d[u],(int)(fee+Ask(t.u,t.v,0)-Ask(t.u,t.v,1)));
}
S[1].add(id[u],id[u],d[u]);
}
int main()
{
// freopen("hdu5293.in","r",stdin);
int T;cin>>T;
while(T--) {
MEM(edge) MEM(Next) MEM(Pre) siz=1;
MEM(d) MEM(s)
For(i,n) a[i].clear();
cin>>n>>m;
S[0].mem(n);S[1].mem(n);
For(i,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
addedge2(u,v);
}
build();
For(i,m) {
int u,v ,w;
scanf("%d%d%d",&u,&v,&w);
a[lca(u,v)].pb(Chain(u,v,w));
}
dfs(1,0);
printf("%d\n",d[1]);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5293(Tree chain problem-树链剖分)
标签:
原文地址:http://blog.csdn.net/nike0good/article/details/48035575