ZOJ - 4048 Red Black Tree (LCA+贪心) The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online
题意:一棵树上有m个红色结点,树的边有权值。q次查询,每次给出k个点,每次查询有且只有一次机会将n个点中任意一个点染红,令k个点中距离红色祖先距离最大的那个点的距离最小化。q次查询相互独立。
分析:数据量很... 最大值最小化,二分搜答案。将ST表求lca的dfs函数加一点东西,求出每个点到其最近红色祖先的距离。check函数中,枚举到其红色祖先的距离超过下限的点。设非法点数为p,尝试将其距离通过一次染色缩小。具体做法是求出这p个点的lca,这个点就是要染红的点,因为只有修改这个点,才有可能将所有点的红祖先距离都缩减。若修改之后仍有结点非法,则check失败
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
struct node{
int v,next;
LL dis;
}edges[N<<1];
int head[N],e;
int id[N]; //节点第一次被遍历的顺序
LL dis[N]; //节点到根节点的距离
LL rdis[N]; //距离最近的红色祖先的距离
bool red[N];
int RMQ[N*2][20];
int curID;
//F[i]表示第i个遍历的节点
//B[i]表示F[i]在树中的深度
int F[N*2],B[N*2];
int n,m,Q,root;
#include<bits/stdc++.h>
using namespace std;
////////////////
namespace IO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) { IOerror = 1; return -1; }
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
inline void read(int &x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (sign)x = -x;
}
inline void read(ll &x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (sign)x = -x;
}
inline void read(double &x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (ch == '.') {
double tmp = 1; ch = nc();
for (; ch >= '0'&&ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0');
}
if (sign)x = -x;
}
inline void read(char *s) {
char ch = nc();
for (; blank(ch); ch = nc());
if (IOerror)return;
for (; !blank(ch) && !IOerror; ch = nc())*s++ = ch;
*s = 0;
}
inline void read(char &c) {
for (c = nc(); blank(c); c = nc());
if (IOerror) { c = -1; return; }
}
//fwrite->write
struct Ostream_fwrite {
char *buf, *p1, *pend;
Ostream_fwrite() { buf = new char[BUF_SIZE]; p1 = buf; pend = buf + BUF_SIZE; }
void out(char ch) {
if (p1 == pend) {
fwrite(buf, 1, BUF_SIZE, stdout); p1 = buf;
}
*p1++ = ch;
}
void print(int x) {
static char s[15], *s1; s1 = s;
if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
while (x)*s1++ = x % 10 + '0', x /= 10;
while (s1-- != s)out(*s1);
}
void println(int x) {
static char s[15], *s1; s1 = s;
if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
while (x)*s1++ = x % 10 + '0', x /= 10;
while (s1-- != s)out(*s1); out('\n');
}
void print(ll x) {
static char s[25], *s1; s1 = s;
if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
while (x)*s1++ = x % 10 + '0', x /= 10;
while (s1-- != s)out(*s1);
}
void println(ll x) {
static char s[25], *s1; s1 = s;
if (!x)*s1++ = '0'; if (x<0)out('-'), x = -x;
while (x)*s1++ = x % 10 + '0', x /= 10;
while (s1-- != s)out(*s1); out('\n');
}
void print(double x, int y) {
static ll mul[] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL };
if (x<-1e-12)out('-'), x = -x; x *= mul[y];
ll x1 = (ll)floor(x); if (x - floor(x) >= 0.5)++x1;
ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y]; print(x2);
if (y>0) { out('.'); for (size_t i = 1; i<y&&x3*mul[i]<mul[y]; out('0'), ++i); print(x3); }
}
void println(double x, int y) { print(x, y); out('\n'); }
void print(char *s) { while (*s)out(*s++); }
void println(char *s) { while (*s)out(*s++); out('\n'); }
void flush() { if (p1 != buf) { fwrite(buf, 1, p1 - buf, stdout); p1 = buf; } }
~Ostream_fwrite() { flush(); }
}Ostream;
inline void print(int x) { Ostream.print(x); }
inline void println(int x) { Ostream.println(x); }
inline void print(char x) { Ostream.out(x); }
inline void println(char x) { Ostream.out(x); Ostream.out('\n'); }
inline void print(ll x) { Ostream.print(x); }
inline void println(ll x) { Ostream.println(x); }
inline void print(double x, int y) { Ostream.print(x, y); }
inline void println(double x, int y) { Ostream.println(x, y); }
inline void print(char *s) { Ostream.print(s); }
inline void println(char *s) { Ostream.println(s); }
inline void println() { Ostream.out('\n'); }
inline void flush() { Ostream.flush(); }
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace IO;
void init()
{
e = 0; curID = 0;
memset(head,-1,sizeof(head));
memset(red,0,sizeof(red));
}
void AddEdge (int u,int v,LL w)
{
edges[e].v=v;
edges[e].dis=w;
edges[e].next=head[u];
head[u]=e++;
}
void DFS (int u,int p,int Dep,LL d)
{
int i,v;
if(red[u]) d=0;
curID++;
rdis[u] = d;
F[curID]=u;
B[curID]=Dep;
id[u]=curID;
for (i=head[u];i!=-1;i=edges[i].next){
v=edges[i].v;
if (v==p) continue;
dis[v]=dis[u] + edges[i].dis;
DFS(v,u,Dep+1,d+edges[i].dis);
curID++;
F[curID]=u;
B[curID]=Dep;
}
}
void initRMQ ()
{
int i,j,x,y;
for (i=1;i<=curID;i++)
RMQ[i][0]=i;
for (j=1;(1<<j)<=curID;j++)
for (i=1;i+(1<<j)-1<=curID;i++){
x=RMQ[i][j-1];
y=RMQ[i+(1<<(j-1))][j-1];
RMQ[i][j]=B[x]<B[y]?x:y;
}
}
int getLCA (int a,int b)
{
int k,x,y;
a=id[a];b=id[b];
if (a>b)
k=a,a=b,b=k;
k = 31 - __builtin_clz(b-a+1);
x=RMQ[a][k];
y=RMQ[b-(1<<k)+1][k];
return B[x]<B[y]?F[x]:F[y];
}
int qq[N],cnt;
int vz[N];
bool check(LL &x)
{
int all =0;
for(int i=0;i<cnt;++i){ //枚举超过限制的结点
if(rdis[qq[i]]>x){
vz[all++] = qq[i];
}
}
if(all==0) return true;
int lca = vz[0];
for(int i=0;i<all;++i){ //求出所有非法结点的lca,这个lca就是要染色的点
lca = getLCA(lca,vz[i]);
}
LL mx = 0;
for(int i=0;i<all;++i){ //查看最长距离
if(dis[vz[i]]-dis[lca]>x) return false;
}
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T; read(T);
while(T--){
int n,M,Q;
int u,v; LL w;
LL up = 0;
init();
read(n), read(M), read(Q);
//scanf("%d %d %d",&n,&M,&Q);
for(int i=1;i<=M;++i){
read(u);
red[u] = 1;
}
red[1] = 1;
for(int i=1;i<n;++i){
//scanf("%d %d %lld",&u,&v,&w);
read(u), read(v), read(w);
AddEdge(u,v,w);
AddEdge(v,u,w);
up += w;
}
DFS(1,0,0,0);
initRMQ();
while(Q--){
int k; read(k);//scanf("%d",&k);
cnt = k;
for(int i=0;i<k;++i){
read(qq[i]);
//scanf("%d",&qq[i]);
}
LL L =0,R = up,mid,ans = up;
while(L<=R){
mid = (L+R)>>1;
if(check(mid)){
ans = mid;
R = mid-1;
}
else L =mid+1;
}
println(ans);
//printf("%lld\n",ans);
}
}
return 0;
}
ZOJ - 4048 Red Black Tree (LCA+贪心) The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online的更多相关文章
- UVALive 7146 Defeat the Enemy(贪心+STL)(2014 Asia Shanghai Regional Contest)
Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. ...
- HDU 3697 Selecting courses(贪心+暴力)(2010 Asia Fuzhou Regional Contest)
Description A new Semester is coming and students are troubling for selecting courses. Students ...
- The 2019 ICPC Asia Shanghai Regional Contest H Tree Partition k、Color Graph
H题意: 给你一个n个节点n-1条无向边构成的树,每一个节点有一个权值wi,你需要把这棵树划分成k个子树,每一个子树的权值是这棵子树上所有节点权值之和. 你要输出这k棵子树的权值中那个最大的.你需要让 ...
- HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)
Problem Description Zero and One are good friends who always have fun with each other. This time, ...
- ZOJ 4062 - Plants vs. Zombies - [二分+贪心][2018 ACM-ICPC Asia Qingdao Regional Problem E]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4062 题意: 现在在一条 $x$ 轴上玩植物大战僵尸,有 $n$ ...
- ZOJ 4067 - Books - [贪心][2018 ACM-ICPC Asia Qingdao Regional Problem J]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4067 题意: 给出 $n$ 本书(编号 $1 \sim n$), ...
- HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...
- UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...
随机推荐
- mysql更改utf8编码方式
方法1: 一.查看数据库编码格式 1 mysql> show variables like 'character_set_database'; 二.查看数据表的编码格式 1 mysql> ...
- hdu 1813(IDA*)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1813 思路:首先bfs预处理出‘0’到边界点最短距离,然后构造 h() 为所’0‘点逃离迷宫的最少步数 ...
- uva 11381(神奇的构图、最小费用最大流)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=29821 思路:首先拆点,每个字符对应的位置拆成i和i+len,然后 ...
- Nuget包制作最佳解决方案
https://www.cnblogs.com/drea/p/8418717.html 最近研究ABP框架,下载其全套源码,想“据为己有”,这样添加功能或者修改源码的话就非常方便了,否则搭建项目直接用 ...
- 编程之美 set 9 字符串移位包含问题
题目 给定字符串 s1 和 s2, 要求判定 s2能否能够被通过 s1 做循环移位得到的字符包含. s1 = AABCD, s2 = CDAA 返回 true. 给定 s1 = ABCD 和 s2 = ...
- zoj3686(线段树的区间更新)
对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a ...
- 部分常用dos命令
Microsoft Windows XP [版本 ] (C) 版权所有 - Microsoft Corp. C:\Documents and Settings\Administrator>d: ...
- ng2-file-upload上传附件同时传参
由于业务需要,需要的场景是发某条公告的时候能够上传附件,不只是图片,图片的话可以直接用base64传给后台,但上传附件这个就不能这样干了, 与此同时,每条公告都有一个对应的唯一标识id, 附件以文件流 ...
- js 闭包与垃圾回收-待删
关于闭包请看戳 串讲-解释篇:作用域,作用域链,执行环境,变量对象,活动对象,闭包,本篇写的不太好: 先摆定义: 函数对象,可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种 ...
- Django -- some config
1.主项目下的url配置:urls.py文件 from django.contrib import adminfrom django.urls import path, includefrom dja ...