出题人居然是个哲学家。。

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的更多相关文章

  1. BZOJ NOI十连测 第二测 T2

    思路:20%可以搜索.. #include<algorithm> #include<cstdio> #include<cmath> #include<cstr ...

  2. BZOJ NOI十连测 第一测 T1

    思路:首先考虑t=1的情况,t等于1,那么所有位置的颜色相同,我们不用考虑概率的问题,那么,k+d*x在模d下都相等,我们考虑预处理一个数组s[i][j],代表d为i,起始位置为j的等差数列的和,这个 ...

  3. BZOJ NOI十连测 第一测 T2

    思路:看到这题,就感觉是一道很熟悉的题目: http://www.cnblogs.com/qzqzgfy/p/5535821.html 只不过这题的K最多可以到N,而且边权不再只是1,考试的时候yy了 ...

  4. 痞子衡嵌入式:测一测i.MXRT1170 Raw NAND启动时间(从POR到进App的Reset_Handler)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 Raw NAND启动时间. 关于i.MXRT1170这颗划时代的MCU,痞子衡去年10月在其刚发布的时候, ...

  5. 「NOI十联测」深邃

    「NOI十联测」深邃 要使得最大的连通块最小,显然先二分答案. 先固定1结点为根. 对于一个果实,显然是先处理子树中未分配的点,再向外延伸. 每个结点记录一个\(si[]\),表示子树中未分配的点数, ...

  6. 「NOI十联测」奥义商店

    「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...

  7. 「NOI十联测」黑暗

    「NOI十联测」黑暗 \(n\) 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 \(m\) 次方,求所有可能的图的权值和.(n≤30000,m≤15) 令\(ans[n][m]\)为n个 ...

  8. NOI十连测 第六测 T1

    思路: 用treap动态维护,记一个sum1,sum2,注意!,写treap如果有删除操作,千万不能把权值相同的分开来..,这在删除的时候会进入死循环,这是一个惨痛的教训... #include< ...

  9. NOI十连测 第五测 T1

    #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #inclu ...

随机推荐

  1. C语言复习--实现栈

    C #include <stdio.h> #include <stdlib.h> #define STACK_SIZE 100 typedef char TYPE; typed ...

  2. BZOJ 1497 最大获利(最大权闭合子图)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1497 思路:由题意可以得知,每个顾客都依赖2个中转站,那么让中转站连有向边到汇点,流量为它的建设费用 ...

  3. OpenWRT 编译 error GNU libiconv not in use but included iconv.h is from...

    OpenWRT 编译 error GNU libiconv not in use but included iconv.h is from... 编译的时候碰到一个常见的错误,但是却在一个陌生的地方爆 ...

  4. windows nfs server for linux

    摘要 在开发嵌入式系统的过程中,为了方便调试与文件共享,需要使用到nfs,即网络文件系统,这位板子的调试测试带来了很大的方便.之前在linux系统下开发,与ARM11核心板 linux系统对接共享也比 ...

  5. Android Studio代码着色插件

    文章将给大家分享Studio中代码高亮插件,个人觉得换个代码着色方式还是挺有必要的,起码让视觉上有个变换,感官上爽一些.就像吃惯了大鱼大肉,偶尔也来点青菜萝卜吧.以下是个人喜欢的几款,给个效果图大家看 ...

  6. Calculate Number Of Islands And Lakes 解答

    Question 1 1 1 1 1 01 0 1 0 0 11 0 1 0 0 11 1 0 1 1 1 1 is earth, 0 is water. i) count the number of ...

  7. mips平台使用jdbc操作sqlite的最终解决方案

    1.概述: 本项目需要在多平台上(mips必须支持)操作嵌入式数据库sqlite,而最新的sqlite-jdbc-3.15.1.jar的本地驱动只含有少量的平台,于是解决支持mips平台实在必行.方法 ...

  8. Unity 命令行参数

    通常情况下,Unity可以通过双击桌面上的图标启动,也可以通过输入命令行启动(例如,MacOS终端或者Windows的CMD窗口),通过这种方式在启动时会接受命令和信息.我们可以制作一些小工具跟Uni ...

  9. pyqt QTableWidgetItem多行显示

    def __2(self): t1=QtGui.QTableWidgetItem(self.names.text()) self.tabs.tableinsertinto.setItem(0,0,t1 ...

  10. 01-Java学习笔记

    本系列笔记由常彦博整理,请知悉 目  录 一. Java技术基础.................................................................... ...