标签:现场赛 节点 sign next display getc 0.00 rem 子节点
3 6 10 1 2 4 2 3 5 1 4 3 4 5 3 5 6 3 6 30 1 2 4 2 3 5 1 4 3 4 5 3 5 6 3 6 50 1 2 4 2 3 5 1 4 3 4 5 3 5 6 3
51 75 81HintIn the second case, the best transportation time is: ? The 2-th city: 16 = 4^2 ? The 3-th city: 72 = 4^2 + 30 + 5^2 ? The 4-th city: 9 = 3^2 ? The 5-th city: 36 = (3 + 3)^2 ? The 6-th city: 75 = (3 + 3)^2 +30 + 3^2 Consequently, the news in the 6-th city requires most time to reach the capital.
写了树分治双log的做法,被hdu卡掉了。
本来想看看别人怎么写的,结果发现网上目前只有暴力回溯的题解
一个菊花图,然后子节点特别优的话就能卡掉了。只是数据似乎没这么做。
先说一下树分治思路吧。
len[i]表示从1到i的长度
朴素方程f[i]=max(f[j]+(len[j]-len[i])^2)+p
然后假设j在k上面j比k优
(f[j]+(len[j]-len[i])^2)+p<(f[k]+(len[k]-len[i])^2)+p
移项得到斜率方程
((f[k]+len[k]*len[k])-(f[j]+len[j]*len[j]))/((len[k]-len[j])*2)>len[i]
右边有单调性
维护斜率单调减即可
具体做法是,对于某个重心,我们先分治重心上面的,再分治重心下面的。
分治的时候我们从重心往上跳到当前的根,将这段链维护一个凸包
重心下面的点按照到重心的长度排序,然后依次从凸包队首弹出元素直到最优,从队首转移即可
先丢个代码吧,对拍了一下应该没问题了,不过hdu上会T。现场应该是可以过的
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
update:卡了卡常后选了个没人评测没人抢评测资源的时候交,过了
原代码:
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct line { int s,t; int x; int next; bool flag; }a[200001]; int head[100001]; int edge; inline void add(int s,int t,int x) { a[edge].next=head[s]; head[s]=edge; a[edge].s=s; a[edge].t=t; a[edge].x=x; a[edge].flag=true; } long long len[100001]; long long f[100001]; int fa[100001]; inline bool cmp(int x,int y) { return len[x]>len[y]; } inline void getl(int d) { int i; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(t!=fa[d]) { fa[t]=d; len[t]=len[d]+a[i].x; getl(t); } } } int mini,minx; int son[100001]; bool v[100001]; inline void find(int d,int s) { son[d]=0; int i; int tmp=0; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(a[i].flag&&t!=fa[d]) { find(t,s); son[d]+=(son[t]+1); tmp=max(tmp,son[t]+1); } } int mx=max(tmp,s-tmp-1); if(mx<minx) { minx=mx; mini=d; } } int sx[100001],dis[100001],px[100001]; int P; inline double getk(int k,int j) { return (double)((f[k]+len[k]*len[k])-(f[j]+len[j]*len[j]))/double(len[k]-len[j])/double(2); } int ps; inline void gets(int d) { int i; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(a[i].flag&&t!=fa[d]) { int t=a[i].t; ps++; px[ps]=t; gets(t); } } } int q[100001]; inline void solve(int d,int size,int zx) { if(size==1) return ; if(size==2) { if(len[zx]>len[d]) f[zx]=min(f[zx],f[d]+(len[zx]-len[d])*(len[zx]-len[d])+P); return ; } int i; int ttx=son[zx]; son[d]-=son[zx]; for(i=head[zx];i!=0;i=a[i].next) a[i].flag=false; minx=2100000000; mini=0; find(d,son[d]+1); solve(d,son[d]+1,mini); for(i=head[zx];i!=0;i=a[i].next) a[i].flag=true; // ps=1; // px[ps]=zx; ps=0; gets(zx); sort(px+1,px+1+ps,cmp); int dx=zx; int l=1,r=0,lt=1; while(dx!=fa[d]) { while(l<r&&getk(q[r-1],q[r])<getk(q[r],dx)) r--; r++; q[r]=dx; dx=fa[dx]; } for(i=1;i<=ps;i++) { while(l<r&&getk(q[l],q[l+1])>len[px[i]]) l++; if(px[i]==1) continue; f[px[i]]=f[q[l]]+(len[px[i]]-len[q[l]])*(len[px[i]]-len[q[l]])+P; } find(zx,ttx+1); for(i=head[zx];i!=0;i=a[i].next) { int t=a[i].t; if(t==fa[zx]) continue; minx=2100000000; mini=0; find(t,son[t]+1); solve(t,son[t]+1,mini); } } int main() { // freopen("I.in","r",stdin); // freopen("I.out","w",stdout); int T; // scanf("%d",&T); T=read(); while(T>0) { T--; int n; n=read(); P=read(); //scanf("%d%d",&n,&P); int i; int s,t,x; memset(head,0,sizeof(head)); edge=0; for(i=1;i<=n-1;i++) { s=read(); t=read(); x=read(); //scanf("%d%d%d",&s,&t,&x); edge++; add(s,t,x); edge++; add(t,s,x); } memset(len,0,sizeof(len)); memset(fa,0,sizeof(fa)); getl(1); memset(f,127/3,sizeof(f)); f[1]=0; minx=2100000000; mini=0; find(1,n); solve(1,n,mini); long long ans=0; // for(i=1;i<=n;i++) // printf("%d: %lld\n",i,f[i]); for(i=2;i<=n;i++) ans=max(ans,f[i]); printf("%lld\n",ans-P); } return 0; }
AC代码:
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; /*inline int max(int x,int y) { if(x>y) return x; return y; } inline int min(int x,int y) { if(x<y) return x; return y; }*/ inline long long max(long long x,long long y) { if(x>y) return x; return y; } inline long long min(long long x,long long y) { if(x<y) return x; return y; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct line { int s,t; int x; int next; bool flag; }a[200001]; int head[100001]; int edge; inline void add(int s,int t,int x) { a[edge].next=head[s]; head[s]=edge; a[edge].s=s; a[edge].t=t; a[edge].x=x; a[edge].flag=true; } long long lenx[100001]; long long len[100001]; //int len[100001]; //int f[100001]; long long f[100001]; int fa[100001]; inline bool cmp(int x,int y) { return len[x]>len[y]; } inline void getl(int d) { int i; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(t!=fa[d]) { fa[t]=d; len[t]=len[d]+a[i].x; getl(t); } } } int mini,minx; int son[100001]; bool v[100001]; inline void find(int d,int s) { son[d]=0; int i; int tmp=0; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(a[i].flag&&t!=fa[d]) { find(t,s); son[d]+=(son[t]+1); tmp=max(tmp,son[t]+1); } } int mx=max(tmp,s-tmp-1); if(mx<minx) { minx=mx; mini=d; } } int sx[100001],dis[100001],px[100001]; int P; /*inline double getk(int k,int j) { return (double)((f[k]+len[k]*len[k])-(f[j]+len[j]*len[j]))/double(len[k]-len[j])/double(2); }*/ inline bool check(int k1,int j1,int k2,int j2) { return ((f[k1]+lenx[k1])-(f[j1]+lenx[j1]))*(len[k2]-len[j2])<((f[k2]+lenx[k2])-(f[j2]+lenx[j2]))*(len[k1]-len[j1]); } inline int checkk(int k,int j,int lenxt) { return ((f[k]+lenx[k])-(f[j]+lenx[j]))>lenxt*2*(len[k]-len[j]); } int ps; inline void gets(int d) { int i; for(i=head[d];i!=0;i=a[i].next) { int t=a[i].t; if(a[i].flag&&t!=fa[d]) { ps++; px[ps]=t; gets(t); } } } int q[100001]; inline void solve(int d,int size,int zx) { if(size==1) return ; if(size==2) { if(len[zx]>len[d]) f[zx]=min(f[zx],f[d]+(len[zx]-len[d])*(len[zx]-len[d])+P); return ; } int i; int ttx=son[zx]; son[d]-=son[zx]; for(i=head[zx];i!=0;i=a[i].next) a[i].flag=false; minx=2100000000; mini=0; find(d,son[d]+1); solve(d,son[d]+1,mini); for(i=head[zx];i!=0;i=a[i].next) a[i].flag=true; // ps=1; // px[ps]=zx; ps=0; gets(zx); sort(px+1,px+1+ps,cmp); int dx=zx; int l=1,r=0,lt=1; while(dx!=fa[d]) { // while(l<r&&getk(q[r-1],q[r])<getk(q[r],dx)) while(l<r&&check(q[r-1],q[r],q[r],dx)) r--; r++; q[r]=dx; dx=fa[dx]; } for(i=1;i<=ps;i++) { // while(l<r&&getk(q[l],q[l+1])>len[px[i]]) while(l<r&&checkk(q[l],q[l+1],len[px[i]])) l++; if(px[i]==1) continue; f[px[i]]=min(f[px[i]],f[q[l]]+(len[px[i]]-len[q[l]])*(len[px[i]]-len[q[l]])+P); } //find(zx,ttx+1); for(i=head[zx];i!=0;i=a[i].next) { int t=a[i].t; if(t==fa[zx]) continue; minx=2100000000; mini=0; find(t,son[t]+1); solve(t,son[t]+1,mini); } } int main() { // freopen("I.in","r",stdin); // freopen("I.out","w",stdout); int T; // scanf("%d",&T); T=read(); while(T>0) { T--; int n; n=read(); P=read(); //scanf("%d%d",&n,&P); if(n==1) { printf("0\n"); continue; } int i; int s,t,x; memset(head,0,sizeof(head)); edge=0; for(i=1;i<=n-1;i++) { s=read(); t=read(); x=read(); //scanf("%d%d%d",&s,&t,&x); edge++; add(s,t,x); edge++; add(t,s,x); } memset(fa,0,sizeof(fa)); getl(1); for(i=1;i<=n;i++) lenx[i]=(long long)len[i]*(long long)len[i]; memset(f,127/3,sizeof(f)); f[1]=0; minx=2100000000; mini=0; find(1,n); solve(1,n,mini); long long ans=0; // for(i=1;i<=n;i++) // printf("%d: %lld\n",i,f[i]); for(i=2;i<=n;i++) ans=max(ans,f[i]); printf("%lld\n",ans-P); } return 0; }
hdu 5956 The Elder 2016ACM/ICPC沈阳赛区现场赛I
标签:现场赛 节点 sign next display getc 0.00 rem 子节点
原文地址:http://blog.csdn.net/lqybzx/article/details/52983551