题意:给你一棵新树,树的每个节点都有一个权值,告诉你其实这棵树是由另一棵原树转化过来的进行的操作是,把原树每个点的权值变成了该点为根的子树中权值的最大值,原树的所有的点的权值按标号排下来是一个1-n的排列
根是不固定的
请你找出这个原树,输出标号顺序下字典序最小的权值排列

字典序最小=贪心地填法

首先要发现一些规律
1.对于新树,选的root的权值一定是n
2.新树上以n为权值的点一定是构成一条链,而我们选根必须是链的两个端点rt1,rt2
选这两个是都能做的,但是选标号更小的作根更好,这样可以把n填在标号更大的点里,使得字典序更小
3.在填的时候,impossible的情况出现在该点权值比所有的儿子的权值还小的情况,一个点给出时就用过两次的情况,还有最后没得填的情况
4.填的时候只有一个原则,就是这个点填的原树权值一定要比新树权值小(是自己的情况之前已经处理过)
那么可以考虑贪心地填(看的题解)
从大到小看标号,填入 最接近小于 该位置新值的 未用的值,不会用set,维护了一个线段树,区间记录还没填的最右的标号

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <stack>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#define pii pair<int,int>
#define xx first
#define yy second
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
vector<int>p[100005];
int a[100005], ans[100005], rt1, rt2, n, mx[100005], mxt[100005], f[100005];
bool vis[100005];
bool fail = 0;struct node
{int l, r, v;
}t[100005*4];void build( int l, int r, int x )
{t[x].l = l, t[x].r = r;int mid = (l+r) >> 1;if( l == r ){t[x].v = l;return ;}build( l, mid, x<<1 );build( mid+1, r, x<<1|1 );t[x].v = max( t[x<<1].v, t[x<<1|1].v );
}void update( int pos, int x )
{int l = t[x].l, r = t[x].r, mid;mid = (l+r)>>1;if( l == r && l == pos ){if( t[x].v == -10000000 ) fail = 1;// 尝试两次填同一个点t[x].v = -10000000;return ;}if( pos <= mid  ) update( pos, x<<1 );else update( pos, x<<1|1 );t[x].v = max( t[x<<1].v, t[x<<1|1].v );
}int query( int L, int R, int x )
{if( L > R ) return -10000000;int l = t[x].l, r = t[x].r, mid;mid = (l+r)>>1;if( L == l && r == R ){return t[x].v;}if( L > mid ) return query( L, R, x<<1|1 );else if( R <= mid ) return query( L, R, x<<1 );else{int tp = query( mid+1, R, x<<1|1 );if( tp != -10000000 ) return tp;else return query( L, mid, x<<1 );}
}void findrt( int now, int fa )
{int i, v, fl = 0;for( i = 0; i < p[now].size(); i ++ ){v = p[now][i];if( a[v] == n ) fl ++;if( v == fa ) continue;if( a[v] == n ) findrt( v, now );}if( fl == 1 && rt1 == 0 ) rt1 = now;else if( fl == 1 && rt1 != 0 && rt2 == 0 ) rt2 = now;
}void dfs_mx( int now, int fa )
{int i, v;mx[now] = 0;f[now] = fa;for( i = 0; i < p[now].size(); i ++ ){v = p[now][i];if( v == fa ) continue;dfs_mx( v, now );mx[now] = max( mx[now], mx[v] );}if( a[now] > mx[now] ) ans[now] = a[now], update( a[now], 1 );mxt[now] = mx[now];// mxt为子树不包含自己的最大值,mx为包含自己的最大值mx[now] = max( a[now], mx[now] );
}int main()
{int m, i, j, x, y;int cas = 1, T;// freopen("1002.in", "r", stdin);// freopen("out.out", "w", stdout);scanf("%d", &T);while( T -- ){scanf("%d", &n);//if( cas == 18 ) printf("%d\n", n);for( i = 1; i <= n; i ++ ) p[i].clear();memset( ans, 0, sizeof(ans) );for( i = 1; i <= n; i ++ ){scanf("%d", &a[i]);//if( cas == 15 ) printf("%d ", a[i]);}for( i = 1; i <= n-1; i ++ ){scanf("%d %d", &x, &y);//if( cas == 15 ) printf("%d %d\n", x, y);p[x].push_back(y);p[y].push_back(x);}printf("Case #%d:", cas++);if( n == 1 ){printf(" 1\n");continue;}build( 1, n, 1 );fail = 0;rt1 = rt2 = 0;int x;for( i = 1; i <= n; i ++ ){if( a[i] == n ){x = i;break;}}findrt( x, -1 );if( rt1 > rt2 && rt2 != 0 ) swap( rt1, rt2 );if( x != 0 && rt1 == 0 && rt2 == 0 ){rt1 = x;}//printf("%d %d\n", rt1, rt2);dfs_mx( rt1, -1 );for( i = 1; i <= n; i ++ ){if( a[i] < mxt[i] ){fail = 1;break;}}if( fail ){printf(" Impossible\n");continue;}for( i = n; i >= 1; i -- ){if( !ans[i] ){int id = query( 1, a[i]-1, 1 );if( id == -10000000 ){fail = 1;break;}else{ans[i] = id;update( id, 1 );}}}if( fail ){printf(" Impossible\n");continue;}for( i = 1; i <= n; i ++ ) printf(" %d", ans[i]);printf("\n");}
}

2016 多校4 1002 After a Sleepless Night 树上贪心相关推荐

  1. 2016多校赛2 A 数学推公式 E 极角排序,组合数(待补) L dp+bitset优化

    2016 Multi-University Training Contest 2 A - Acperience 题意:给出w[],求S((w[i]-aB[i])^2)的最小值(B[i]为1或-1). ...

  2. 2016 多校赛3 A 水 B 期望,规律 C 各种博弈 J 物理题,积分 K 暴力,水

    2016 Multi-University Training Contest 3 A - Sqrt Bo 题意:给一个数 n,问n要多少次平方后化为1,如果超过5次输出"TAT". ...

  3. 计算机校本培训心得,2016信息技术校本研修心得体会

    导语:校本培训.是基于学校,为了学校,发展学校的研修.要切实开展在综合教育改革背景下的校本研修,需要多角度.多方面地整合力量,创造良好的校本研修生态环境,让教师在专家引领.同伴互助.个体反思实践中实现 ...

  4. 2016弱校联萌十一专场10.2

    F.floyd-warshell 20000个点,距离为1的所有边求最短路 感觉就是单纯的生成树求最短路(最近公共祖先) 然后把去掉的边还原 把涉及的点bfs一下拼出最短路 赛场注意不要被这种题目吓到 ...

  5. 2016百度星资格赛1002 大数相加

    不多说 如题 为了保存代码 1 #include<iostream> 2 #include<climits> 3 #include <cstdlib> 4 #inc ...

  6. 2016多校联合训练1 B题Chess (博弈论 SG函数)

    题目大意:一个n(n<=1000)行,20列的棋盘上有一些棋子,两个人下棋,每回合可以把任意一个棋子向右移动到这一行的离这个棋子最近的空格上(注意这里不一定是移动最后一个棋子),不能移动到棋盘外 ...

  7. [弱校联萌2016]2016弱校联盟十一专场10.2

    比赛链接:https://www.bnuoj.com/v3/contest_show.php?cid=8520 A.无非两种情况,点在体里和点在体外.在体外分三种情况,分别是到顶点的距离最小.到棱的距 ...

  8. 2016弱校联盟十一专场10.2部分题解

    2/10 传送门 H. Around the World 1 /*zhen hao*/ 2 #include <bits/stdc++.h> 3 using namespace std; ...

  9. [弱校联萌2016]2016弱校联盟十一专场10.3

    比赛链接:https://www.bnuoj.com/v3/contest_show.php?cid=8504#info A.找两个数乘积是连续上升并且最大的. 1 #include <bits ...

最新文章

  1. Redis实现分布式锁全局锁—Redis客户端Redisson中分布式锁RLock实现
  2. 【Flutter】Dart 面向对象 ( 类定义 | 类的继承 | 私有变量 | 可选参数 | 默认参数 | 初始化列表 )
  3. HASH Partitioning--转载
  4. 在不知道根节点的情况下生成树形结构 (采用JSONObject)
  5. HDU2015校赛 The Country List
  6. linux用户的根目录_为什么Linux允许用户删除根目录?
  7. jpa 根据主键生成策略获取id_如何在使用JPA和Hibernate时选择id生成策略
  8. 启动kafka报错:__consumer_offsets-22\00000000000000000000.index.swap: 另一个程序正在使用此文件,进程无法访问。
  9. SSM框架搭建过程----学生学籍管理系统
  10. android nds模拟器窗口,安卓NDS模拟器drastic模拟器使用经验分享
  11. 在eclipse中如何搭建ssh框架
  12. 计算机科学与技术考研多少分算高分,清华计算机科学与技术系考研初复试高分经验分享...
  13. 责任链模式 php,每天一个设计模式之(9)-----责任链模式
  14. js实现数字转换大写金额
  15. 海思Hi3531DV100开发环境搭建
  16. C++求一元二次方程根
  17. 让计算机网络与作文教学,“基于计算机和网络环境下的写作教学研究”课题组  2015-2016学年度上学期研究计划...
  18. 火狐浏览器怎么设置打开书签的时候在新标签页打开
  19. 小红伞免费杀毒软件设置优化
  20. 优秀的图文识别开源项目PandaOCR

热门文章

  1. idea创建maven项目失败,没有src目录
  2. 【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(二)
  3. extrinsic parameters外部参数radial distortion畸变参
  4. 我们重写了七层流量代理BFE的路由转发机制
  5. PHP在线发邮件 无需服务端软件
  6. C# EPL USB 指令打印
  7. 2022世界VR产业大会圆满收官,酷雷曼惊艳亮相!
  8. 读取html到超级列表框,超级列表框读取TXT文本配置内容
  9. pygame 制作飞机大战项目
  10. 饥荒联机云服务器_WeGame饥荒联机版专用服务器多层世界搭建教程