并不对劲的loj2179:p3714:[BJOI2017]树的难题
生活随笔
收集整理的這篇文章主要介紹了
并不对劲的loj2179:p3714:[BJOI2017]树的难题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目大意
有一棵樹,\(n\)(\(n\leq2*10^5\))個點,每條邊\(i\)有顏色\(w_i\),共有\(m\)(\(m\leq n\))種顏色,第\(i\)種顏色的權值是\(c_i\)(\(|c_i|\leq10^4\))
定義一條路徑的權值是該路徑上所有同色段的顏色的權值之和
給定\(l,r\),求邊數在\([l,r]\)中權值最大的路徑的權值
題解
將每個點的所有邊按顏色排序后,對這棵樹進行點分治,每次統計過當前重心的路徑
用線段樹統計應該挺板的吧
有人用單調隊列做,然而我不會,先坑著
代碼
#include<algorithm> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<iomanip> #include<iostream> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define rep(i,x,y) for(register int i=(x);i<=(y);++i) #define dwn(i,x,y) for(register int i=(x);i>=(y);--i) #define pii pair<int ,int> #define fi first #define se second #define mp make_pair #define pb push_back #define maxn 200010 #define inf 2147483647 #define ls (u<<1) #define rs (u<<1|1) #define mi (L+R>>1) #define vv(x) v[x][i].se using namespace std; int read() {int x=0,f=1;char ch=getchar();while(!isdigit(ch)&&ch!='-')ch=getchar();if(ch=='-')f=-1,ch=getchar();while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();return x*f; } void write(int x) {if(x==0){putchar('0'),putchar('\n');return;}int f=0;char ch[20];if(x<0)putchar('-'),x=-x;while(x)ch[++f]=x%10+'0',x/=10;while(f)putchar(ch[f--]);putchar('\n');return; } int n,m,l,r,ans=-inf,wt,sumsiz,mnsz,vis[maxn]; long long cnt; int siz[maxn],c[maxn]; vector<pii >v[maxn]; struct tree {int tr[maxn<<2],mk[maxn<<2];void pu(int u){tr[u]=max(tr[ls],tr[rs]);}void mark(int u,int k){mk[u]=tr[u]=k;}void pd(int u){if(mk[u]){mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}}void add(int u,int L,int R,int x,int k){if(x<=L&&R<=x){tr[u]=max(k,tr[u]),mk[u]=0;return;}pd(u);if(x<=mi)add(ls,L,mi,x,k);else add(rs,mi+1,R,x,k);return pu(u);}int ask(int u,int L,int R,int x,int y){if(y<L||R<x)return -inf;if(x<=L&&R<=y)return tr[u];pd(u);int res=-inf;if(x<=mi)res=ask(ls,L,mi,x,y);if(y>mi)res=max(res,ask(rs,mi+1,R,x,y));return res;} }t[2]; void getwt(int u,int fa) {siz[u]=1;int nwmx=0,lim=v[u].size();rep(i,0,lim-1)if(vv(u)!=fa&&!vis[vv(u)])getwt(vv(u),u),siz[u]+=siz[vv(u)],nwmx=max(nwmx,siz[vv(u)]);nwmx=max(nwmx,sumsiz-siz[u]);if(nwmx<mnsz)wt=u,mnsz=nwmx;return; } void asktr(int u,int fa,int fac,int dep,int num) {if(dep>r)return;int lim=v[u].size(),tmp=max(t[0].ask(1,0,n,l-dep,r-dep),t[1].ask(1,0,n,l-dep,r-dep));if(tmp!=-inf)ans=max(ans,tmp+num);rep(i,0,lim-1)if(!vis[vv(u)]&&vv(u)!=fa)asktr(vv(u),u,v[u][i].fi,dep+1,num+(v[u][i].fi==fac?0:c[v[u][i].fi])); } void addtr(int u,int fa,int fac,int dep,int num,int f) {if(dep>r)return;int lim=v[u].size();t[f].add(1,0,n,dep,num);rep(i,0,lim-1)if(!vis[vv(u)]&&vv(u)!=fa)addtr(vv(u),u,v[u][i].fi,dep+1,num+(v[u][i].fi==fac?0:c[v[u][i].fi]),f); } void getans(int u,int nowsiz) {sumsiz=nowsiz,mnsz=n+1,getwt(u,0);int now=wt;int lim=v[now].size(),p=0;t[0].mark(1,-inf),t[1].mark(1,-inf);t[0].add(1,0,n,0,0);cnt+=(long long)nowsiz;rep(i,0,lim-1){if(!vis[vv(now)]){asktr(vv(now),now,v[now][i].fi,1,c[v[now][i].fi]),addtr(vv(now),now,v[now][i].fi,1,0,1);}if(i!=lim-1&&v[now][i].fi!=v[now][i+1].fi){rep(j,p,i)if(!vis[v[now][j].se])addtr(v[now][j].se,now,v[now][j].fi,1,c[v[now][j].fi],0);t[1].mark(1,-inf);p=i+1;}}vis[now]=1;rep(i,0,lim-1)if(!vis[vv(now)])getans(vv(now),siz[vv(now)]>siz[now]?nowsiz-siz[now]:siz[vv(now)]);return; } int main() {n=read(),m=read(),l=read(),r=read();if(l<=0&&0<=r)ans=0;rep(i,1,m)c[i]=read();rep(i,1,n-1){int x=read(),y=read(),z=read();v[x].pb(mp(z,y)),v[y].pb(mp(z,x));}rep(i,1,n)sort(v[i].begin(),v[i].end());getans(1,n);write(ans);return 0; } /* 5 3 1 4 -1 -5 -2 1 2 1 1 3 1 2 4 2 2 5 3 */ /* 8 4 3 4 -7 9 6 1 1 2 1 1 3 2 1 4 1 2 5 1 5 6 2 3 7 1 3 8 3 */轉載于:https://www.cnblogs.com/xzyf/p/10455146.html
總結
以上是生活随笔為你收集整理的并不对劲的loj2179:p3714:[BJOI2017]树的难题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 倒影问题(reflect:below)
- 下一篇: ThreadLocal的学习