传送门

(要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来

结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解。

首先这个数量肯定是下界,更少的话连第一次都带不走。

然后考虑带过去之后把某一只留在对岸,剩下的全部随身携带,这时有了一个空位,就可以慢慢把与留下的动物无关联的都挪到对岸去。再把随身携带的动物中与未到达对岸的任何一只都无关联的动物留着,其余的(包括之前单出来的)随身携带,这时有了一个空位可以再次慢慢挪。

唯一的特殊情况是某一个点连接了剩余所有点,且总点数大于3,特判即可。

接着是如何计算第一次最少带多少只的问题。

取父亲必定不比取儿子差,我们可以维护这个贪心,这样就只有一种解。

考虑某次多了一个点,肯定是从这个点往上某条链的状态取反,这条链延伸的终点必定是一个已取的点有其他未取的儿子。

树剖之后维护每个点未取的轻儿子的个数,每次查询需要在线段树上二分一下。虽然看起来是两个log,但是明显跑不满,可以A(水)掉。

#include<cstdio>
#include<algorithm>
#define MN 1100000
#define lp p<<1
#define rp p<<1|1
using namespace std; int n,T,f[MN],_s[MN],l[MN],num,df[MN],lo[MN],s[MN],nm,son[MN],to[MN],ANS,t[MN<<],Z[MN<<],c[MN],w[MN],st[MN];
bool b[MN<<];
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
struct na{int y,ne;}B[MN<<];
inline void add(int x,int y){B[++num].y=y;B[num].ne=l[x];l[x]=num;}
void dfs(int x){
s[x]=;son[x]=;
for (int i=l[x];i;i=B[i].ne) if (dfs(B[i].y),s[x]+=s[B[i].y],s[B[i].y]>s[son[x]]) son[x]=B[i].y;
}
void DFS(int x,int q){
df[x]=++nm;to[x]=q;
if (son[x]) DFS(son[x],q);
for (int i=l[x];i;i=B[i].ne)
if (B[i].y!=son[x]) DFS(B[i].y,B[i].y);
lo[x]=nm;
}
inline void rev(int p){
b[p]^=;
}
inline void pd(int p,int l,int r){
if (b[p])
if (b[p]=,l!=r) rev(lp),rev(rp);
else c[l]^=;
}
void fz(int p,int l,int r,int L,int R){
if (l==L&&r==R) {rev(p);return;}
pd(p,l,r);
int mid=l+r>>;
if (R<=mid) fz(lp,l,mid,L,R);else
if (L>mid) fz(rp,mid+,r,L,R);else
fz(lp,l,mid,L,mid),fz(rp,mid+,r,mid+,R);
}
int ask(int p,int l,int r,int L,int R){
//printf("%d %d %d %d %d %d %d %d\n",p,l,r,L,R,t[p],t[lp],t[rp]);
if (!t[p]) return ;
if (l==L&&r==R) return Z[p];
pd(p,l,r);
int mid=l+r>>,tmp;
if (R<=mid) return ask(lp,l,mid,L,R);else
if (L>mid) return ask(rp,mid+,r,L,R);else
if (tmp=ask(rp,mid+,r,mid+,R)) return tmp;else return ask(lp,l,mid,L,mid);
}
bool col(int p,int l,int r,int k){
pd(p,l,r);
if (l==r) return c[k];
int mid=l+r>>;
if (k<=mid) return col(lp,l,mid,k);else return col(rp,mid+,r,k);
}
void ADD(int p,int l,int r,int k,int v){
t[p]+=v;
if (l==r){
Z[p]=t[p]?l:;
return;
}
int mid=l+r>>;
if (k<=mid) ADD(lp,l,mid,k,v);else ADD(rp,mid+,r,k,v);
if (t[p]) if (t[rp]) Z[p]=Z[rp];else Z[p]=Z[lp];else Z[p]=;
}
inline void work(int x){
int tmp,top=,la=;
while (x){
if (son[x]&&col(,,n,df[x]+)) break;
if (tmp=ask(,,n,df[to[x]],df[x])){
if (tmp!=df[x]) fz(,,n,tmp+,df[x]),la=tmp+;
break;
}
//printf("===%d %d\n",x,tmp);
fz(,,n,df[to[x]],df[x]);
la=df[to[x]];
if (f[to[x]]){
if (col(,,n,df[to[x]])){
st[++top]=f[to[x]];
}else if (--w[f[to[x]]]==) ADD(,,n,df[f[to[x]]],-);
}
x=f[to[x]];
}
while (top){
if (w[st[top]]++==) ADD(,,n,df[st[top]],);
top--;
}
ANS+=!col(,,n,la);
//printf("la:%d %d\n",la,col(1,1,n,la));
//for (int j=1;j<=n;j++) printf("col %d %d:%d\n",j,df[j],col(1,1,n,df[j]));
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for (int i=;i<=n;i++) _s[i]=l[i]=s[i]=son[i]=c[i]=w[i]=to[i]=;num=nm=ANS=;
for (int i=;i<=(n<<);i++) t[i]=b[i]=Z[i]=;
for (int i=;i<=n;i++){
scanf("%d",&f[i]);
add(f[i],i);
}
dfs();
DFS(,);
work();
for (int i=;i<=n;i++){
_s[f[i]]++;
work(i);
printf("%d ",ANS++((_s[]==i-&&i>||_s[]==&&_s[]==i-&&i>)));
//printf("%d\n",ANS);
}
puts("");
}
}

Codechef August Challenge 2018 : Chef at the River的更多相关文章

  1. Codechef August Challenge 2018 : Safe Partition

    传送门 (虽然是A了但是不知道复杂度是不是正确的 考虑以某个位置为结尾的合法划分 先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足m ...

  2. Codechef August Challenge 2018 : Interactive Matrix

    传送门 首先整个矩阵可以被分为很多小矩阵,小矩阵内所有行的单调性是一样的,所有列的单调性是一样的. 考虑如何在这样一个小矩阵中找出答案.我的策略是每次取四个角中最大值和最小值的点,这样可以每次删掉一行 ...

  3. Codechef August Challenge 2018 : Lonely Cycles

    传送门 几波树形dp就行了. #include<cstdio> #include<cstring> #include<algorithm> #define MN 5 ...

  4. Codechef August Challenge 2018 : Coordinate Compression

    传送门 外边二分,里面拿线段树维护贪心就行了. #include<cstdio> #include<vector> #include<cstring> #inclu ...

  5. Codechef August Challenge 2018 : Modular GCD

    传送门 一开始还手动拓欧找规律,发现好像玩不了. 然后想了想,A-B这个数比较小,枚举它的因子判断合不合法就行了. 需要特判A=B的情况. #include<cstdio> #includ ...

  6. 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair

    第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...

  7. Codechef August Challenge 2019 Chef and Gordon Ramsay

    [传送门] 题目即求所有的三元组,相对大小关系同 $p_1,p_2,p_3$. 题解说都很清楚,这里写一下过程整理一下思路. 如果我们枚举中间这个元素,那么就是统计子树内外有多少个大于这个数和小于这个 ...

  8. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  9. Codechef September Challenge 2018 游记

    Codechef September Challenge 2018 游记 Magician versus Chef 题目大意: 有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格 ...

随机推荐

  1. Centos 7最小化redis部署

    配置源 [GuGe] name=GuGe baseurl=ftp://192.168.1.82 gpgcheck= enable= 安装 sh-4.2# yum -y install gcc gcc- ...

  2. openstack项目【day24】:VLAN模式

    本节内容 一 二层基础知识 1.1 vlan介绍 1.1.1:vlan的含义 1.1.2:vlan的类型 1.1.3:vlan的不足 1.2 : 二层交换的基础知识 1.2.1:二层交换机最基本的功能 ...

  3. LFYZ-OJ ID: 1016 输油管道问题

    分析 根据之前的证明,我们已经知道最佳输油管线的y位置就是所有油井y坐标序列的中位数,故解题过程为: 1. 读入n个y数据 2. 对n个y数据进行排序(升序或降序) 3. 求中位数zws 4. 计算输 ...

  4. Javaweb学习笔记——(二十三)——————AJAX、XStream、JSON

    AJAX概述     1.什么是AJAX         ajax(Asynchronous JavaScript and xml) 翻译成中文就是"异步JavaScript和xml&quo ...

  5. IP、端口及远程服务器

  6. Centos7 安装 python2.7

    Centos7 安装 python 2.7.15 和 pip  1.先安装 GCC 包,如果没安装 GCC包 就输入以下命令行安装: (*注:以下记得使用 su 权限) yum install gcc ...

  7. Max Area of Island

    Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...

  8. python中的赋值操作

    参考:https://www.cnblogs.com/andywenzhi/p/7453374.html?tdsourcetag=s_pcqq_aiomsg(写的蛮好) python中的赋值操作“=” ...

  9. PostgreSQL快速入门

    一.PostgreSQL是什么? PostgreSQL是一个功能强大的开源对象关系数据库管理系统(ORDBMS). 用于安全地存储数据; 支持最佳做法,并允许在处理请求时检索它们. PostgreSQ ...

  10. Set集合判断对象重复的方法

    Set<User> userSet = new HashSet<>(); User user1= new User("aa","11") ...