BZOJ NOI十连测 第二测 T1
出题人居然是个哲学家。。
26%的程序,太SB了。。。本来我的想法也是二分+贪心,但是贪心是个怪怪的SX贪心。。
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<time.h>
#define inf 0x7fffffff
struct edge{
int u,v,id;
}e[];
int tot,go[],first[],next[];
int Tot,Go[],First[],Next[];
int c[],b[],son[],ans,vis[],pd;
int pass[],op[],C[],Cnt,block,sum,B[];
int id1,id2;
int n,k;
int read(){
char ch=getchar();int t=,f=;
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void Dfs(int x,int fa){
if (vis[x]) return;
c[x]=b[x];son[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
if (pass[i]) continue;
Dfs(pur,x);
son[x]+=son[pur];
c[x]+=c[pur];
}
if (c[x]&&(n-c[x]>)) ans=std::min(ans,std::max(son[x],n-son[x]));
}
void sbpianfen(){
ans=inf;
Dfs(,);
printf("%d\n",ans);
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
pass[tot]=;
}
void add(int x,int y){
insert(x,y);op[tot]=tot+;insert(y,x);op[tot]=tot-;
}
void Insert(int x,int y){
Tot++;
Go[Tot]=y;
Next[Tot]=First[x];
First[x]=Tot;
}
void Add(int x,int y){
Insert(x,y);Insert(y,x);
}
int bfs(int x){
int h=,t=;
bool ck=;
c[]=x;vis[x]=;if (b[x]) ck=;
while (h<=t){
int now=c[h++];
for (int i=First[now];i;i=Next[i]){
int pur=Go[i];
if (vis[pur]) continue;
c[++t]=pur;
vis[pur]=;
if (b[pur]) ck=;
}
}
if (!ck) pd=;
return t;
}
void dFs(int x){
if (x==n){
pd=;
int bl=;
for (int i=;i<=n;i++)
First[i]=;
Tot=;
for (int i=;i<n;i++)
if (!e[i].id) Add(e[i].u,e[i].v);
for (int i=;i<=n;i++)
vis[i]=;
for (int i=;i<=n;i++)
if (!vis[i])
bl=std::max(bl,bfs(i));
if (pd==) ans=std::min(ans,bl);
return;
}
e[x].id=;
dFs(x+);
e[x].id=;
dFs(x+);
}
void sxpianfen(){
for (int i=;i<n;i++) e[i].id=;
dFs();
}
void clear(int x){
int h=,t=;
C[]=x;
bool ppp=;
if (b[x]) Cnt++,ppp=;
vis[x]=;b[x]=;
while (h<=t){
int now=C[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (pass[i]) continue;
if (vis[pur]) continue;
C[++t]=pur;
vis[pur]=;
if (b[pur]) Cnt++,ppp=;
b[pur]=;
}
}
if (ppp) {
pd=;
return;
}
if (t>block) pd=;
sum-=t;
}
void work(int x,int mid,int fa,int Edge){
if (c[x]==&&b[fa]==&&son[x]<=block) {
pass[Edge]=;
pass[op[Edge]]=;
clear(x);
id1=x;id2=fa;
if (pd) return;
return;
}
else
if (k-Cnt-c[x]==&&b[x]==&&sum-son[x]<=block){
pass[Edge]=;
pass[op[Edge]]=;
clear(fa);
id1=x;id2=fa;
if (pd) return;
return;
}
else
if (c[x]==&&son[x]<=block&&son[fa]>=block){
pass[Edge]=;
pass[op[Edge]]=;
clear(x);
id1=x;id2=fa;
if (pd) return;
return;
}else
if (k-Cnt-c[x]==&&sum-son[x]==block){
pass[Edge]=;
pass[op[Edge]]=;
clear(fa);
id1=x;id2=fa;
if (pd) return;
return;
}
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
if (vis[pur]) continue;
if (pass[i]) continue;
work(pur,mid,x,i);
}
}
bool check(int mid){
for (int i=;i<n;i++) std::swap(e[rand()%(n-)+],e[rand()%(n-)+]);
for (int i=;i<=n;i++) first[i]=;
tot=;
for (int i=;i<n;i++)
add(e[i].u,e[i].v);
block=mid;pd=;
for (int i=;i<=tot;i++)
pass[i]=;
for (int i=;i<=n;i++)
b[i]=B[i],vis[i]=;
id1=;id2=;vis[]=;
sum=n;Cnt=;
for (int i=;i<=k;i++){
if (vis[id1]&&vis[id2]) break;
if (k-Cnt==) break;
if (!vis[id1]){
Dfs(id1,);
work(id1,mid,,);
}else{
Dfs(id2,);
work(id2,mid,,);
}
if (pd) return ;
}
for (int i=;i<=n;i++)
if (!vis[i]) clear(i);
if (pd) return ;
return ;
}
void solve(){
int l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/;
if (check(mid)) r=mid-,Ans=mid;
else l=mid+;
}
printf("%d\n",Ans);
}
void solve2(){
int l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/;
if (check(mid)) r=mid-,Ans=mid;
else l=mid+;
}
int Tn=Ans;
l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/;
if (check(mid)) r=mid-,Ans=mid;
else l=mid+;
}
Tn=std::min(Tn,Ans);
printf("%d\n",Tn);
}
int main(){
//♂
freopen("deep.in","r",stdin);
freopen("deep.out","w",stdout);
srand(time(NULL));
ans=inf;
n=read();k=read();
for (int i=;i<n;i++){
int x=read(),y=read();
add(x,y);
e[i].u=x;e[i].v=y;
}
for (int i=;i<=k;i++){
int x=read();
b[x]=;B[x]=;
}
if (n<=) {sxpianfen();printf("%d\n",ans);return ;}
if (k==) {printf("%d\n",n);return ;}
if (k==) {sbpianfen();return ;}
if (n<=) {solve();return ;}
if (k==) {solve2();return ;}
if (k==n) {printf("%d\n",);return ;}
if (k==n-) {printf("%d\n",);return ;}
solve();
}
AC程序不知道短到哪里去了
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define N 200005
int tot,go[N*],next[N*],first[N];
int n,k,b[N],fa[N],mx[N],sum[N],vis[N],c[N];
int read(){
char ch=getchar();int t=,f=;
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void bfs(){
int h=,t=;for (int i=;i<=n;i++) vis[i]=;
c[]=;
vis[]=;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
vis[pur]=;
c[++t]=pur;
fa[pur]=now;
}
}
}
bool check(int mid){
int f;
memset(sum,,sizeof sum);
memset(mx,,sizeof mx);
for (int i=n;i>=;i--){
int u=c[i];
if (b[u]) mx[u]=mid-;
else sum[u]++;
f=(mx[u]>=sum[u])?mx[u]-sum[u]:-sum[u];
if (u==&&f<) return ;
if (f<) sum[fa[u]]-=f;
else mx[fa[u]]=std::max(mx[fa[u]],f);
}
return ;
}
int main(){
n=read();k=read();
for (int i=;i<n;i++){
int x=read(),y=read();
add(x,y);
}
for (int i=;i<=k;i++){
int x=read();
b[x]=;
}
bfs();
int l=n/k,r=n,ans;
while (l<=r){
int mid=(l+r)>>;
if (check(mid)) r=mid-,ans=mid;
else l=mid+;
}
printf("%d\n",ans);
}
BZOJ NOI十连测 第二测 T1的更多相关文章
- BZOJ NOI十连测 第二测 T2
思路:20%可以搜索.. #include<algorithm> #include<cstdio> #include<cmath> #include<cstr ...
- BZOJ NOI十连测 第一测 T1
思路:首先考虑t=1的情况,t等于1,那么所有位置的颜色相同,我们不用考虑概率的问题,那么,k+d*x在模d下都相等,我们考虑预处理一个数组s[i][j],代表d为i,起始位置为j的等差数列的和,这个 ...
- BZOJ NOI十连测 第一测 T2
思路:看到这题,就感觉是一道很熟悉的题目: http://www.cnblogs.com/qzqzgfy/p/5535821.html 只不过这题的K最多可以到N,而且边权不再只是1,考试的时候yy了 ...
- 痞子衡嵌入式:测一测i.MXRT1170 Raw NAND启动时间(从POR到进App的Reset_Handler)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 Raw NAND启动时间. 关于i.MXRT1170这颗划时代的MCU,痞子衡去年10月在其刚发布的时候, ...
- 「NOI十联测」深邃
「NOI十联测」深邃 要使得最大的连通块最小,显然先二分答案. 先固定1结点为根. 对于一个果实,显然是先处理子树中未分配的点,再向外延伸. 每个结点记录一个\(si[]\),表示子树中未分配的点数, ...
- 「NOI十联测」奥义商店
「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...
- 「NOI十联测」黑暗
「NOI十联测」黑暗 \(n\) 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 \(m\) 次方,求所有可能的图的权值和.(n≤30000,m≤15) 令\(ans[n][m]\)为n个 ...
- NOI十连测 第六测 T1
思路: 用treap动态维护,记一个sum1,sum2,注意!,写treap如果有删除操作,千万不能把权值相同的分开来..,这在删除的时候会进入死循环,这是一个惨痛的教训... #include< ...
- NOI十连测 第五测 T1
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #inclu ...
随机推荐
- SIM卡基础,各管脚意义,封装定义
1. SIM简介 SIM卡(Subscriber Identity Module).即用户识别模块,是一张符合GSM规范的"智慧卡".SIM卡可以插入任何一部符合GSM规范的移动电 ...
- JAVA Stack栈和Heap堆的区别(转)
首先分清楚Stack,Heap的中文翻译:Stack—栈,Heap—堆. 在中文里,Stack可以翻译为“堆栈”,所以我直接查找了计算机术语里面堆和栈开头的词语: ...
- Eclipse vim插件安装使用
在eclipse移动关闭位置感觉非常不爽,经常要用到方向键和鼠标,导致经常要移来移去.果断受不了了,去网上搜了下发现eclipse有许多vim插件可以使用.有一个大家都比较推荐的是 vrapper ...
- 插入排序(Insertion Sort)
这是排序算法中最常见的排序方法,也是初学者使用最多的.有时候我们在生活中也会不自觉地用到插入排序,例如: 给手里的牌排序 这是最常见的例子之一,我们通常从纸牌的一边开始看,找到一张位置不正确的,把它拿 ...
- Best Cow Line (POJ 3217)
给定长度为N的字符串S,要构造一个长度为N的字符串T,起初,T是一个空串,随后反复进行下列任意操作. *从S的头部删除一个字符,加到T的尾部 *从S的尾部删除一个字符,加到T的尾部 目标是要构造字典序 ...
- 04747_Java语言程序设计(一)_第4章_数组和字符串
面试题 字符串连接 public class Aserver { public static void main(String args[]) { // 字符串数据和其他数据+,结果是字符串类型 // ...
- MySQL查询随机数据的4种方法和性能对比
从MySQL随机选取数据也是我们最常用的一种发发,其最简单的办法就是使用”ORDER BY RAND()”,本文介绍了包括ORDER BY RAND()的4种获取随机数据的方法,并分析了各自的优缺点. ...
- 用JUnit4进行参数化测试
参数化测试是一个JUnit 3不具备的功能. 基本使用方法 @RunWith 当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner) ...
- python - 文件
''' 模式 描述 r 以读方式打开文件,可读取文件信息. w 以写方式打开文件,可向文件写入信息.如文件存在,则清空该文件,再写入新内容 a 以追加模式打开文件(即一打开文件,文件指针自动移到文件末 ...
- hdu 5063 Operation the Sequence(Bestcoder Round #13)
Operation the Sequence Time Limi ...