HDU 5029 Relief grain(恶心的树链剖分 + 线段树)
来源:互联网 发布:趣头条提现是骗局 知乎 编辑:程序博客网 时间:2024/04/30 23:32
题意:
n个村庄分配粮食,m次分配,每一次分配树上的l~r区间村庄内某种粮食*1,询问每个村庄最多粮食数量的种类是什么
分析:
首先注意到题目要求在树上的路径分配粮食,很容易想到用树链剖分和线段树去处理区间查找过程
如果此时强行将每个区间内的粮食数量及种类全部存下来,很明显内存会爆掉,试过了。。。
此处则行不通,也是关键要解决的问题
稍微观察一下,注意到没有更新操作,完全可以离线,很快发现其实对于粮食的分配可以根据种类排序
由于每个村庄的答案唯一,并且在后一种类来之前,前一种类的粮食一定是分配完成的,那么此时在线段树上递归pushdown就能不断更新最大种类的粮食
C++ 提交 4992ms 强行卡过 排名最后。。。(谁让我懒,用vector呢。。。)
#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 200005int n,m;int x[maxn],y[maxn],c[maxn];int fir[maxn],v[maxn],nex[maxn],e_max;int son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],pos[maxn],tot;int L[2*maxn],R[2*maxn];int now;vector<int>vec[2*maxn],num[2*maxn],tmp,tmp1;int lazy[2*maxn];int e[maxn];void init_(){ memset(son,-1,sizeof son); memset(siz,0,sizeof siz); memset(fir,-1,sizeof fir); tot=1; e_max=0; now=0;}void add_edge(int s,int t){ int e=e_max++; v[e]=t; nex[e]=fir[s]; fir[s]=e;}bool cmp(int a,int b){ return c[a]<c[b];}void dfs1(int k,int pre,int d){ deep[k]=d; fa[k]=pre; siz[k]++; for(int i=fir[k]; ~i; i=nex[i]) { int r=v[i]; if(r!=pre) { dfs1(r,k,d+1); siz[k]+=siz[r]; if(son[k]==-1||siz[son[k]]<siz[r]) son[k]=r; } }}void dfs2(int k,int sp){ top[k]=sp; pos[k]=tot++; if(son[k]==-1) return ; dfs2(son[k],sp); for(int i=fir[k]; ~i; i=nex[i]) { int r=v[i]; if(r!=fa[k]&&r!=son[k]) { dfs2(r,r); } }}void init(int l,int r,int k){ L[k]=l; R[k]=r; vec[k].clear(); num[k].clear(); lazy[k]=0; if(l==r) return ; int mid=l+r>>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1);}void special(int k,int d,int n){ if(vec[k].size()==0) { vec[k].push_back(d); num[k].push_back(n); lazy[k]=d; return ; } if(vec[k].size()==1||lazy[k]==d) { if(vec[k][0]==d) { num[k][0]+=n; } else { vec[k].push_back(d); num[k].push_back(n); if(num[k][1]>num[k][0]) { swap(num[k][0],num[k][1]); swap(vec[k][0],vec[k][1]); lazy[k]=vec[k][0]; vec[k].resize(1); num[k].resize(1); } } return ; } if(vec[k][1]==d) { num[k][1]+=n; if(num[k][1]>num[k][0]) { swap(num[k][0],num[k][1]); swap(vec[k][0],vec[k][1]); lazy[k]=vec[k][0]; vec[k].resize(1); num[k].resize(1); } } else { if(num[k][1]>num[k][0]) { swap(num[k][0],num[k][1]); swap(vec[k][0],vec[k][1]); lazy[k]=vec[k][0]; } vec[k].resize(1); num[k].resize(1); vec[k].push_back(d); num[k].push_back(n); if(num[k][1]>num[k][0]) { swap(num[k][0],num[k][1]); swap(vec[k][0],vec[k][1]); lazy[k]=vec[k][0]; vec[k].resize(1); num[k].resize(1); } }}void Resize(int d,int n,int k){ if(L[k]==R[k]) { special(k,d,n); return ; } if(vec[k].size()==0) { vec[k].push_back(d); num[k].push_back(n); lazy[k]=d; return ; } if(lazy[k]==d) { num[k][0]+=n; return ; } if(num[k][0]>=n&&now!=d) return ; Resize(vec[k][0],num[k][0],k<<1); Resize(vec[k][0],num[k][0],k<<1|1); vec[k].clear(); num[k].clear(); vec[k].push_back(d); num[k].push_back(n); lazy[k]=d;}void pushdown(int k){ if(vec[k].size()==0) return ; Resize(vec[k][0],num[k][0],k<<1); Resize(vec[k][0],num[k][0],k<<1|1); vec[k].clear(); num[k].clear(); lazy[k]=0;}void update(int d,int s,int t,int l,int r,int k){ if(s==l&&r==t) { if(s==t) { special(k,d,1); } else if(lazy[k]==0) { vec[k].push_back(d); num[k].push_back(1); lazy[k]=d; } else if(lazy[k]==d) { num[k][0]++; } else { pushdown(k); vec[k].push_back(d); num[k].push_back(1); lazy[k]=d; } return ; } pushdown(k); int mid=l+r>>1; if(t<=mid) update(d,s,t,l,mid,k<<1); else if(s>mid) update(d,s,t,mid+1,r,k<<1|1); else { update(d,s,mid,l,mid,k<<1); update(d,mid+1,t,mid+1,r,k<<1|1); }}void query(int d,int l,int r,int k){ if(l==d&&r==d) { tmp=vec[k]; tmp1=num[k]; return ; } pushdown(k); int mid=l+r>>1; if(d<=mid) query(d,l,mid,k<<1); else query(d,mid+1,r,k<<1|1);}void Change(int s,int t,int r){ int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t); update(r,pos[f1],pos[s],1,tot-1,1); s=fa[f1]; f1=top[s]; } if(deep[s]>deep[t]) swap(s,t); update(r,pos[s],pos[t],1,tot-1,1);}int main(){ while(scanf("%d%d",&n,&m)!=EOF&&n+m) { init_(); for(int i=1; i<n; i++) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } for(int i=0; i<m; i++) { scanf("%d%d%d",&x[i],&y[i],&c[i]); e[i]=i; } dfs1(1,-1,1); dfs2(1,1); init(1,tot-1,1); sort(e,e+m,cmp); for(int i=0; i<m; i++) { int r=e[i]; now=c[r]; Change(x[r],y[r],c[r]); } for(int i=1; i<=n; i++) { query(pos[i],1,tot-1,1); int val=0; int sum=0; for(int j=0; j<tmp.size(); j++) { if(tmp1[j]>sum) sum=tmp1[j],val=tmp[j]; } printf("%d\n",val); } } return 0;}/*5 41 22 33 44 51 5 11 3 21 2 21 1 39 171 21 32 42 58 49 46 37 34 5 15 4 14 5 14 5 25 4 25 4 25 4 24 5 34 5 34 5 34 5 34 8 44 8 44 8 44 8 44 8 48 4 4*/
0 0
- HDU 5029 Relief grain(恶心的树链剖分 + 线段树)
- hdu 5029 Relief grain (树链剖分+线段树)
- hdu 5029 Relief grain(树链剖分+线段树)
- HDU 5029Relief grain(树链剖分+线段树)
- HDU 5029 Relief grain 树链剖分+线段树离线维护
- HDU 5029 Relief grain 树链剖分 离线 线段树
- HDU 5029 Relief grain (树链剖分 + 线段树)
- [HDU 5029] Relief grain (树链剖分+线段树)
- HDU 5029Relief grain-树链剖分+线段树+离线
- hdu 5029 Relief grain 树链剖分
- hdu 5029 Relief grain 树链剖分
- HDU 5209 Relief grain 解题报告(树链剖分 + 线段树)
- HDU 5029 Relief grain
- hdu 5029 Relief grain
- HDU5029 Relief grain(树链剖分+线段树)
- Hdu 5029 Relief grain(树链剖分)
- HDU 5029 Relief grain(树链剖分)
- HDU 5029 Relief grain --树链剖分第一题
- String、StringBuffer、StringBuilder 性能测试
- 修改MySql密码
- POJ 2777 Count Color
- 日期计算
- Codeforces 444C DZY Loves Colors
- HDU 5029 Relief grain(恶心的树链剖分 + 线段树)
- 杭电-2098 分拆素数和 (素数打表)
- 29. Divide Two Integers
- Extjs MVC架构
- hdoj 1997 汉诺塔VII 《递归》
- 一天的记录
- VS2013_MFC编程问题
- 一次给新电脑安装pod--ios辅助开发工具 的过程 (转)
- 浅谈fork与vfork函数