【GDOI2017第三轮模拟day2】树的难题(点剖,树状数组)
来源:互联网 发布:linux 重启oracle 编辑:程序博客网 时间:2024/05/16 05:59
Description
Solution
一看就知道是点剖,但是还要套上一个数据结构,感觉很麻烦,比赛的时候直接上暴力。
点剖的时候在分治中心的时候,因为发现颜色是一个很麻烦的东西,所以考虑对直系儿子的颜色进行排序,然后对同一个颜色的开一个树状数组,然后对整体开一个树状数组,用树状数组log方的时间求最大值(如果r-lowbit < l那么r–)
这样做是
但是还是要打一个小优化,如果mx(颜色最大值)*size>ans那么就退出
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;typedef long long ll;const int maxn=2e5+7,inf=0x7fffffff/2;int i,j,k,l,n,m,r,x,y,z,tot,tou,tot1,qian;int c[maxn],first[maxn*2],last[maxn*2],next[maxn*2],chang[maxn*2],num,size[maxn],d[2][maxn];bool bz[maxn],az[2][maxn];ll t[2][maxn],g[2][maxn],o,w,da,dian,ans;struct node{ int se,len;ll sum;}a[maxn];struct nod{ int se,a;}b[maxn];bool cmp(nod x,nod y){return x.se<y.se;}void ad(int x,int y,int z){ last[++num]=y,next[num]=first[x],first[x]=num,chang[num]=z;}void clear(int o){ int i,p;fo(i,1,d[o][0])p=d[o][i],az[o][p]=0,t[o][p]=g[o][p]=-inf; d[o][0]=0;}void add(int o,int x,ll y){ g[o][x]=(g[o][x]<y)?y:g[o][x]; for(;x<=maxn-7;x+=(x&-x)){ if(!az[o][x])d[o][++d[o][0]]=x,az[o][x]=1; t[o][x]=(t[o][x]<y)?y:t[o][x]; }}int find(int o,int l,int r){ ll z=-inf; while(l<=r){ if(r-(r&-r)+1>=l)z=(z<t[o][r])?t[o][r]:z,r-=(r&-r); else z=(z<g[o][r])?g[o][r]:z,r--; } return z;}void dfs1(int x,int y){ int i;size[x]=1; rep(i,x)if(!bz[last[i]]&&last[i]!=y)dfs1(last[i],x),size[x]+=size[last[i]];}void dfs2(int x,int y){ int i;bool az=1; rep(i,x)if(!bz[last[i]]&&last[i]!=y){ if(size[last[i]]>dian/2)az=0; dfs2(last[i],x); } if(az&&dian-size[x]<=dian/2)z=x;}void dfs3(int x,int y,int z,int u,ll sum){ int i; if(z>r)return; a[++tot]=(node){tou,z,sum}; if(z>=l)ans=(ans<sum)?sum:ans; rep(i,x){ if(last[i]!=y&&!bz[last[i]]){ if(u==chang[i])dfs3(last[i],x,z+1,u,sum); else dfs3(last[i],x,z+1,chang[i],sum+c[chang[i]]); } }}void fen(int x){ int i,j; dfs1(x,0);dian=size[x];dfs2(x,0);x=z;bz[x]=1; if(ans>da*dian)return; tot1=tot=0; rep(i,x)if(!bz[last[i]])b[++tot1].se=chang[i],b[tot1].a=last[i]; sort(b+1,b+1+tot1,cmp); clear(0); b[++tot1].se=b[tot1-1].se+1;b[0].se=b[1].se; fo(i,1,tot1){ if(b[i].se!=b[i-1].se){ fo(j,1,tot){ w=(1<l-a[j].len)?l-a[j].len:1; o=find(0,w,r-a[j].len)+a[j].sum; ans=(ans<o)?o:ans; } if(i==tot1)continue; fo(j,1,tot)add(0,a[j].len,a[j].sum);tot=0; clear(1); } tou=b[i].se;qian=tot; dfs3(b[i].a,0,1,b[i].se,c[b[i].se]); if(b[i].se==b[i-1].se){ fo(j,qian+1,tot){ w=(1<l-a[j].len)?l-a[j].len:1; o=find(1,w,r-a[j].len)+a[j].sum-c[a[j].se]; ans=(ans<o)?o:ans; } fo(j,qian+1,tot)add(1,a[j].len,a[j].sum); } } clear(1); rep(i,x)if(!bz[last[i]])fen(last[i]);}int main(){ freopen("journey.in","r",stdin); freopen("journey.out","w",stdout); scanf("%d%d%d%d",&n,&m,&l,&r);ans=da=-inf; fo(i,1,m)scanf("%d",&c[i]),da=(da<c[i])?c[i]:da; fo(i,1,n-1){ scanf("%d%d%d",&x,&y,&z); ad(x,y,z);ad(y,x,z); t[0][i]=t[1][i]=g[0][i]=g[1][i]=-inf; } fen(n/2); printf("%lld\n",ans);}
1 0
- 【GDOI2017第三轮模拟day2】树的难题(点剖,树状数组)
- 【JZOJ5077】【GDOI2017第三轮模拟day2】树的难题
- 【JZOJ5078】【GDOI2017第三轮模拟day2】魔法咒语
- GDOI2017第三轮模拟总结
- GDOI2017第三轮模拟总结
- GDOI2017模拟第三轮总结
- 【jzoj5078】【GDOI2017第三轮模拟day2】【魔法咒语】【ac自动机】【矩阵快速幂】
- [JZOJ5078].[AC自动机复习]【GDOI2017第三轮模拟day2】魔法咒语
- 【GDOI2017第三轮模拟day2】魔法咒语(AC自动机,矩阵乘法)
- 【GDOI2017模拟】树的难题
- 【GDOI2017第三轮模拟day1】影魔(主席树)
- [JZOJ5073]【GDOI2017第三轮模拟day1】影魔
- 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔
- jzoj【GDOI2017第二轮模拟day2】开房间
- 【GDOI2017第二轮模拟day2】中位数
- 【GDOI2017第二轮模拟day2】开房间
- 【GDOI2017第二轮模拟day2】中位数
- 【GDOI2017第二轮模拟day2】开房间
- MongoDB基本语法
- C++set
- js实现往表格动态添加学生的学号、姓名、语数英的考试成绩和总分(总分不是填写),实现行与行之的颜色相间,高光的效果
- JAVAWEB开发之Spring详解之——AOP底层剖析(基于JDK和cglib)、Spring中的AOP以及基于AspectJ的AOP实现、Spring的JDBCTemplate详解
- Objective-C Method Swizzling
- 【GDOI2017第三轮模拟day2】树的难题(点剖,树状数组)
- C与C++中的const用法
- uboot的Makefile分析
- V4L2视频采集与视频编码学习目录及总结
- 克隆二叉树
- 泛型数组+泛型嵌套+泛型应用实例
- 无聊写的 一个Soeckt 客户端例子
- 贪心 【还要做题】
- 图像处理与计算机视觉:基础,经典以及最近发展