传送门

(要是没有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. Redis的Cluster配置

    Redis的Cluster配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装Redis并启动 1>.修改Redis的配置文件(本实验只有三个节点) [root@no ...

  2. Sass学习第一天

    Sass学习 网站学习地址: Sass中文网:https://www.sass.hk/docs/#t7-3 Airen的博客:https://www.w3cplus.com/preprocessor/ ...

  3. css中font-size为0的妙用(消除内联元素间的间隔)

    前言 <div> <input type="text"> <input type="button" value="提交& ...

  4. mysql/mariadb主从复制

    主从复制简介 MySQL数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据库文件,而是通过binlog日志复制到需要同步的从服务器上. MySQL数据库支持单向.双向.链式级联, ...

  5. Spring Security 之基本概念

    Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Spring S ...

  6. [再寄小读者之数学篇](2014-06-23 Bernstein's inequality)

    $$\bex \supp \hat u\subset \sed{2^{j-2}\leq |\xi|\leq 2^j} \ra \cfrac{1}{C}2^{jk}\sen{f}_{L^p} \leq ...

  7. ERROR [main] master.HMasterCommandLine Master exiting

    2018-05-18 07:07:26,257 INFO [main-SendThread(localhost:2181)] zookeeper.ClientCnxn: Opening socket ...

  8. 「WC2018」通道

    没有代码能力... LOJ #2339 Luogu P4220 UOJ #347 题意 给定三棵树$ T1,T2,T3$,求一个点对$ (x,y)$使得$ T1.dist(x,y)+T2.dist(x ...

  9. 论文笔记:Cross-Domain Visual Matching via Generalized Similarity Measure and Feature Learning

    Cross-Domain Visual Matching,即跨域视觉匹配.所谓跨域,指的是数据的分布不一样,简单点说,就是两种数据「看起来」不像.如下图中,(a)一般的正面照片和各种背景角度下拍摄的照 ...

  10. Encode and Decode TinyURL

    TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/desi ...