hdu 5764 After a Sleepless Night(2016多校第四场1002) 线段树
来源:互联网 发布:unity3d里字母 编辑:程序博客网 时间:2024/05/17 07:07
显然对于值为n的点一定构成链,然后我们只需要把两端最小的点作为根(为了字典序),然后就好办了,对于每棵子树根一定是最大值,然后最大值也一定形成链,这样我们就能把所有能确定的点确定下来(根的底端),然后不能确定的点的值一定小于等于输入的全值,下面介绍个人的处理方法:
我们从没有分配的最小的权值开始,因为字典序所以要分配给序号小的点,那么怎么办,我们可以先把所有未分配的店按输入的权值从小到大排序,对于每个点看看输入权值之前能分配多少个权值,如果分配个数大于这个点之前没有分配的点的数量,那么就能从这个点的后面取点扔到这个点的前面,用线段树维护即可。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int maxn=100005;vector<int>g[maxn];int vis[maxn];int use[maxn];int a[maxn];int in[maxn];int ans[maxn];int s[maxn];int fa[maxn];int find(int pa){ if(fa[pa]==-1||fa[pa]==pa) return fa[pa]=pa; return fa[pa]=find(fa[pa]);}void init(int n){ for(int i=0;i<=n;i++){ vis[i]=0; in[i]=0; fa[i]=-1; use[i]=0; ans[i]=0; g[i].clear(); }}int flag;void dfs(int u,int pa){ int cnt=0; for(int v:g[u]){ if(v!=pa){ if(a[v]>a[u]){ flag=1; return; } if(a[v]==a[u]){ cnt++; } } } if(cnt>1){ flag=1; return; } if(cnt==0){ ans[u]=a[u]; if(use[a[u]]){ flag=1; return; } use[a[u]]=1; } for(int v:g[u]){ if(v!=pa) dfs(v,u); }}int x[maxn],y[maxn],to[maxn];int cmp(int x,int y){ if(a[x]!=a[y]) return a[x]<a[y]; return x<y;}struct pi{ int le,ri; int m1; int m2; int lazy;}pp[maxn<<2];void build(int tot,int l,int r){ pp[tot].le=l; pp[tot].ri=r; pp[tot].lazy=0; if(l==r){ pp[tot].m1=x[l]; pp[tot].m2=s[a[x[l]]]-l; return; } build(2*tot,l,(l+r)/2); build(2*tot+1,(l+r)/2+1,r); pp[tot].m1=min(pp[2*tot].m1,pp[2*tot+1].m1); pp[tot].m2=min(pp[2*tot].m2,pp[2*tot+1].m2);}void merg1(int tot,int x){ if(pp[tot].le==pp[tot].ri){ pp[tot].m1=1000000000; return; } int mid=(pp[tot].le+pp[tot].ri)/2; if(x<=mid) merg1(2*tot,x); else merg1(2*tot+1,x); pp[tot].m1=min(pp[2*tot].m1,pp[2*tot+1].m1);}void merg2(int tot,int l,int r,int la){ if(l>r) return; if(pp[tot].le>=l&&pp[tot].ri<=r){ pp[tot].lazy+=la; return; } int mid=(pp[tot].le+pp[tot].ri)/2; if(l<=mid) merg2(2*tot,l,r,la); if(r>mid) merg2(2*tot+1,l,r,la); pp[tot].m2=min(pp[2*tot].m2+pp[2*tot].lazy,pp[2*tot+1].m2+pp[2*tot+1].lazy);}int query(int tot,int all){ if(all+pp[tot].lazy+pp[tot].m2>0) return pp[tot].ri+1; if(pp[tot].le==pp[tot].ri) return pp[tot].le; all+=pp[tot].lazy; int s= query(2*tot,all); if(s<=pp[2*tot].ri) return s; return query(2*tot+1,all);}int query1(int tot,int l,int r){ if(pp[tot].le>=l&&pp[tot].ri<=r) return pp[tot].m1; int s=1000000000; int mid=(pp[tot].le+pp[tot].ri)/2; if(l<=mid) s=min(s,query1(2*tot,l,r)); if(r>mid) s=min(s,query1(2*tot+1,l,r)); return s;}int main(){ int t,N=0; cin>>t; while(t--){ int n; scanf("%d",&n); init(n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } for(int i=1;i<=n;i++){ if(a[i]==n){ vis[i]=1; } } for(int i=1;i<=n;i++){ if(!vis[i]) continue; for(int v:g[i]){ if(vis[v]){ fa[find(i)]=find(v); if(i<v){ in[i]++; in[v]++; } } } } int all=0; flag=0; for(int i=1;i<=n;i++){ if(vis[i]){ if(all==0){ all=find(i); } else{ if(all!=find(i)){ flag=1; } } } } if(all==0) flag=1; if(flag){ printf("Case #%d: Impossible\n",++N); continue; } for(int i=1;i<=n;i++){ if(vis[i]){ if(in[i]>2){ flag=1; } } } if(flag){ printf("Case #%d: Impossible\n",++N); continue; } int root=0; for(int i=1;i<=n;i++){ if(vis[i]){ if(in[i]==1||in[i]==0){ root=i; break; } } } dfs(root,-1); if(flag){ printf("Case #%d: Impossible\n",++N); continue; } int tot=0; for(int i=1;i<=n;i++){ if(ans[i]==0) x[++tot]=i; } if(tot==0){ printf("Case #%d:",++N); for(int i=1;i<=n;i++) printf(" %d",ans[i]); printf("\n"); continue; } sort(x+1,x+tot+1,cmp); tot=0; for(int i=1;i<=n;i++){ s[i]=s[i-1]; if(use[i]==0){ y[++tot]=i; s[i]++; } } for(int i=1;i<=tot;i++){ if(s[a[x[i]]]<i){ flag=1; break; } } if(flag){ printf("Case #%d: Impossible\n",++N); continue; } for(int i=1;i<=tot;i++) to[x[i]]=i; build(1,1,tot); for(int i=1;i<=tot;i++){ int w=query(1,0); if(w>tot){ w=query1(1,1,tot); ans[w]=y[i]; } else{ int w1=query1(1,1,w); ans[w1]=y[i]; w=w1; } merg1(1,to[w]); merg2(1,1,to[w]-1,-1); merg2(1,to[w],to[w],1000000000); } printf("Case #%d:",++N); for(int i=1;i<=n;i++) printf(" %d",ans[i]); printf("\n"); }}
0 0
- hdu 5764 After a Sleepless Night(2016多校第四场1002) 线段树
- HDU 5764 After a Sleepless Night
- HDU 5764 After a Sleepless Night
- HDU 5764 After a Sleepless Night(dfs)
- 2016 多校4 1002 After a Sleepless Night 树上贪心
- [HDU5764] After a Sleepless Night [2016 Multi-University Training Contest 4(2016多校联合训练4) B]
- HDU 4638 Group 多校第四场(线段树+离线询问)
- HDU 4638 多校第四场1007 离线询问,树状数组||线段树维护
- hdu 4902 Nice boat 多校第四场 线段树的区间置数+区间更新
- 2014多校第四场1006 HDU 4902 Nice boat 线段树 区间更新问题
- 多校第四场 1012 hdu 5338 ZZX and Permutations(线段树+树状数组+贪心)
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- Another sleepless night...
- hdu6070 二分+线段树 2017多校第四场1004
- hdu6070 多校第四场 线段树+二分
- HDU 4339 Query2012多校联赛第四场I题(set或者线段树,下面是set解法)
- hdu5775(2016多校第四场,线段树求逆序数)
- sql:商品限购查询语句
- opencv 腐蚀与膨胀
- Spring IOC容器中Bean的生命周期
- 导入和导出
- poj1222 EXTENDED LIGHTS OUT(高斯消元)
- hdu 5764 After a Sleepless Night(2016多校第四场1002) 线段树
- C# 实现 Snowflake算法
- 题目458 小光棍数
- 去掉 NavigationBar 底部的那条黑线
- 【Git/Github学习笔记】Git的工作流程
- 114. Flatten Binary Tree to Linked List
- hdu 3336 Kmp+dp
- vlc缓冲事件添加及缓冲进度
- sql基本语句