[APIO/ctsc2007]
A.风铃
给一棵二叉树,叶子结点是玩具,为使你的弟弟满意,你需要选一个满足下面两个条件的风铃:
(1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层。
(2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点。
你可以交换一个非叶子节点的左右孩子,问至少要交换多少次可以满足或者输出无解。 非叶子节点不超过100000个
题解:题目的限制条件很多,因此很多情况都是无解的,都特判一下。
以下代码卡时间卡空间卡到bzojRank1了
#include<iostream>
#include<cstdio>
#define getchar() (*S++)
#define pa pair<int,int>
#define mk(x) make_pair(x,x)
#define mp(x,y) make_pair(x,y)
#define MN 100000
using namespace std;
char B[<<],*S=B;
inline int read()
{
int x = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-'){getchar();return -;} ch = getchar();}
while(ch >= '' && ch <= ''){x =(x<<)+(x<<) + ch - '';ch = getchar();}
return x;
}
int rt,n,flag=,ans=;
int c[MN+][],dep[MN+];
bool mark[MN+],yes=true;
inline int abs(int x){return x<?-x:x;}
inline int max(int x,int y){return x<y?y:x;}
inline int min(int x,int y){return x<y?x:y;} pa dfs(int x)
{
if(flag>)return mp(,);
if(min(c[x][],c[x][])==-&&max(c[x][],c[x][])!=-) ++flag;
pa dp1,dp2;
if(c[x][]==-) dp1=mk(dep[x]+); else dep[c[x][]]=dep[x]+,dp1=dfs(c[x][]);
if(c[x][]==-) dp2=mk(dep[x]+); else dep[c[x][]]=dep[x]+,dp2=dfs(c[x][]);
int mn=min(dp1.first,dp2.first),mx=max(dp1.second,dp2.second);
if(abs(mx-mn)>||(dp1.first!=dp1.second&&dp2.first!=dp2.second)) flag=;
if(dp1.first<dp2.second)ans++;
return mp(mn,mx);
} int main()
{
fread(B,,<<,stdin);
n=read();
for(register int i=;i<=n;i++)
{
c[i][]=read();c[i][]=read();
if(c[i][]!=-) mark[c[i][]]=;
if(c[i][]!=-) mark[c[i][]]=;
}
for(rt=;mark[rt];++rt);
dfs(rt);
if(flag>) return *puts("-1");
printf("%d\n",ans);
return ;
}
B.数据备份
给定一条直线上n个点,你要两两配出k对,每个点最多只能在一对内,求最小的每队的距离之和。 n<=100000,x<=10^9
题解:这题真的妙......
我们先把每条线段都扔到一个堆里面,然后每次取出堆顶最小的那条线段,假设是连续的四个点a b c d中的bc段,那么我让答案加上bc段之后,加入ab+cd-bc这一段,删去ab和cd两段,取出k次之后,就能得到最优解。
为什么呢:假如你ab,cd只选一段,那么把它换成bc一定更优。假如你两段都不选,那么我把一段更小的换成bc也一定更优。如果你两段都选,没问题,你选择我新加的这一段,bc已经被扣除了,满足条件。 复杂度是nlogn的。
这个其实就类似网络流的退流操作。
#include<iostream>
#include<cstdio>
#include<queue>
#define INF 2000000000
#define MN 100000
#define pa pair<long long,int>
#define mp make_pair
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} long long ans=;
int n,k,ne[MN+],la[MN+],a[MN+],len[MN+];
bool del[MN+];
priority_queue<pa,vector<pa>,greater<pa> > q; int main()
{
n=read();k=read();
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=n+;i++)la[i+]=i,ne[i]=i+;
la[]=;ne[n+]=;
for(int i=;i<=n;i++)
q.push(mp(len[i]=a[i]-a[i-],i));
len[]=len[n+]=INF;
for(int i=;i<=k;i++)
{
while(del[q.top().second])q.pop();
ans+=q.top().first;int x=q.top().second;q.pop();
int a=la[x],b=ne[x];
del[a]=del[b]=;
q.push(mp(len[x]=len[a]+len[b]-len[x],x));
la[x]=la[a];ne[x]=ne[b];
ne[la[a]]=x;la[ne[b]]=x;
}
cout<<ans;
return ;
}
C.动物园zoo
从前有座动物园,那里的动物围成圈。有n个动物,m个小朋友(n<=10000,m<=50000),每个小朋友可以看到连续的5只动物,有自己喜欢的和讨厌的。你现在要移走一些动物,一个小朋友会高兴当有一只她喜欢的动物没被移走或者有一只它讨厌的动物被移走了。求最多可以让几个小朋友高兴。
题解:一开始想到什么最小割之类的.....然而并不是。正解状压dp,用f[i][j]表示前i只动物,最后五只动物的移动情况为j,最多能使几个小朋友高兴,然后就很容易转移啦。
但是这里的动物是围成圈的,可以暴力枚举前四个动物。复杂度$O(n*2^{9}+2^{4}*m)$
位运算真牛逼真好用
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 2000000000
#define MN 10000
#define MP 50000
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
} unsigned int love[MP+],hate[MP+];
int f[MN+][],n,c,ans=,pos[MP+]; void solve(int pre)
{
int k=;
for(int i=;i<=n;i++)
{
int m=k;
for(unsigned int j=;j<;j++)
{
int last=max(f[i-][j+],f[i-][j]);
int ad1=,ad2=;unsigned int th=j<<;
for(k=m;k<=c&&pos[k]==i;k++)
{
if((th&love[k])>||((~th)&hate[k])>) ad1++;
if(((th+)&love[k])>||((~(th+))&hate[k])>) ad2++;
}
f[i][th]=max(f[i][th],last+ad1);
f[i][th+]=max(f[i][th+],last+ad2);
}
}
int j=pre,m=k;
for(unsigned int i=;i<;i++)
{
int ad=;
for(k=m;k<=c;k++)
{
int a=(pos[k]-n);
unsigned int num=((i-((i>>(-a))<<(-a)))<<a)+(j>>(-a));
if((love[k]&num)>||((~num)&hate[k])>) ad++;
}
ans=max(ans,f[n][i]+ad);
}
} void work()
{
for(int num=;num<;num++)
{
memset(f,,sizeof(f));
for(int i=;i<;i++)f[][i]=-INF;f[][num]=;
solve(num);
}
} int main()
{
n=read();c=read();
for(int i=;i<=c;i++)
{
pos[i]=read();
int num1=read(),num2=read();
for(int j=;j<=num1;j++)
love[i]|=<<(-((read()+n-pos[i])%n));
for(int j=;j<=num2;j++)
hate[i]|=<<(-((read()+n-pos[i])%n));
pos[i]+=;
}
work();
printf("%d\n",ans);
return ;
}
[APIO/ctsc2007]的更多相关文章
- [APIO / CTSC2007]数据备份 --- 贪心
[APIO / CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份. 然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公 ...
- BZOJ1150:[APIO/CTSC2007]数据备份——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1150 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的 ...
- 【[APIO/CTSC2007]动物园】状压DP
题目测评:https://www.luogu.org/problemnew/show/P3622 题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围 ...
- BZOJ2288:[POJ Challenge]生日礼物——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2288 ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, . ...
- 【BZOJ 1177】【APIO 2009】Oil
http://www.lydsy.com/JudgeOnline/problem.php?id=1177 前缀和优化,时间复杂度$O(nm)$ 因为数据不全,快速读入会导致RE,切记! #includ ...
- 【BZOJ 2809】【APIO 2012】dispatching
昨天晚上zyf神犇问我的题,虽然我太弱参加不了APIO但也做一做吧. 用小数据拍了无数次总是查不出错来,交上去就WA,后来用国内数据测发现是主席树上区间相减的值没有用long long存,小数据真是没 ...
- 2015 CTSC & APIO滚粗记
o诶人太弱..... 记一发滚粗记以便治疗我的健忘症= = //文章会不定时修改,添加一些内容什么的...因此最好看一下刷新一下(因为有可能你正在看= =我正在写... 5.2 早上9点坐上长达11小 ...
- CTSC&&APIO 2015 酱油记
在北京待了一周多,还是写点记录吧. 人民大学校园还是挺不错的,不过伙食差评. CTSC的题目太神,根本不会搞,一试20二试10分..本来都寄希望于提交答案题的..结果就悲剧了. 然后是听大爷们的论文答 ...
- 【CTSC 2015】&【APIO 2015】酱油记
蒟蒻有幸参加了神犇云集的CTSC & APIO 2015,感觉真是被虐成傻逼了……这几天一直没更新博客,今天就来补一下吧~~(不过不是题解……) Day 0 从太原到北京现在坐高铁只需3小时= ...
随机推荐
- 日志 --BUG记录
2014-12-15日 在做520wawa的免费推广 部署web应用时 错把path设置为"/*",导致启动tomcat时,导致错误 <Context path=&quo ...
- RxSwift 函数响应式编程
Max 在 Boston 上学,在 San Francisco 工作,是一名软件工程师及创业者.当他还在高中的时候就在一家创业公司工作了,他非常喜欢使用 iOS.Android 以及 JavaScri ...
- vue内置指令详解——小白速会
指令 (Directives) 是带有 v- 前缀的特殊属性,职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM. 内置指令 1.v-bind:响应并更新DOM特性:例如:v-bi ...
- ASP.NET MVC编程——单元测试
1自动化测试基本概念 自动化测试分为:单元测试,集成测试,验收测试. 单元测试 检验被测单元的功能,被测单元一般为低级别的组件,如一个类或类方法. 单元测试要满足四个条件:自治的,可重复的,独立的,快 ...
- 在Vim按了ctrl+s后
在windows我们码代码的时候习惯ctrl+s保存: 但在vim中使用ctrl+s之后终端就没反应了... vim: ctrl+s终止屏幕输出,敲的东西都有效,就是看不见. ctrl+q恢复:
- ELK学习总结(1-3)倒排索引
1.倒排索引(反向索引) 一种索引方法,用来存储在全文检索下某个单词在一个/组文档中的存储位置. 常规索引,文档->关键词,费时,得把一个文档全部遍历一遍 倒排索引,关键词->文档,全文搜 ...
- 详解Ajax请求(四)——多个异步请求的执行顺序
首先提出一个问题:点击页面上一个按钮发送两个ajax请求,其中一个请求会不会等待另一个请求执行完毕之后再执行? 答案是:不会,这两个异步请求会同时发送,至于执行的快与慢,要看响应的数据量的大小及后台逻 ...
- 其实你并不懂如何定义一个 PHP 函数
<?php function divide($dividend, $divisor){ return $dividend / $divisor; } echo divide(12, 4); ec ...
- 小技巧-WEB API第一次加载很慢
原文:http://www.afuhao.com/article_articleId-219.shtml 摘要:ASP.NET页面首次打开很慢,但别的页面如果没有访问过,去访问也会慢.你也许认为它是在 ...
- MySQL集合操作类型
SQL语言包含3个集合操作符(union.intersect.expect)以执行各种集合操作. 此外,每个集合操作符可以有两种修饰符:一个表是包含重复项,另一个表是去除重复项(但不一定时所有的重复项 ...