CODE FESTIVAL 2015 決勝(部分)

B - ダイスゲーム

题意:

给\(N\)个\(6\)个面骰子,然后问掷到概率最大的点数是多少。

分析:

随便打表随便发现是\(\huge\left\lfloor N*7/2 \right\rfloor\)

代码略。

C - 寿司タワー

题意:

给出\(N\)和一个长度为\(2N\)的\(01\)串,可以用\(1\)的花费移动其中的任意一个数字,询问使从头开始使每两个都含有\(0\)和\(1\)的最小交换次数。

例如:\(1001\)是一个合法的串,每两个指\((1,2),(3,4)....(2N-1,2N)\)都满足要求。

分析:

发现最多需要\(n\)次才可以交换得到正确的序列。

如果当下已经有一个\(0\)和\(1\)相邻,那么就可以减少一次交换次数。模拟即可。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
int n,ans;
char ch[MAXN];
int main()
{
cin>>n;
cin>>ch ;
ans=2*n;
for(int i=0;i<=2*n-1;i++)
{
if(ch[i]=='0'&&ch[i+1]=='1'||(ch[i]=='1'&&ch[i+1]=='0')){
ans-=2;
i++;
}
}
cout<<ans/2<<endl;
}

H - 焼肉の達人

题意:

给出\(N\)个区间以及大区间长度\(M\),选择部分区间对其进行区间覆盖,其中覆盖了两次及以上的部分不计算贡献,求最多覆盖大区间中的多少。

分析:

做法非常神仙,貌似也有线段树的做法?没有仔细看。

思考贡献的产生以及消失。当选择了一个区间时,这个区间内则都算贡献,当区间重合时,重合部分不算贡献。

观察可以得到如果我们将每一个整点都向前向后连边长度为\(1\),表示这一部分并没有计算贡献,然后对于一段区间,我们将其从头连到尾长度为0表示计算贡献,可以发现跑从\(0\)到\(n\)的最短路就是我们没有计算贡献的最小值,可以堆优化Dijkstra跑一跑。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
struct po
{
int nxt,to,dis;
}edge[MAXN<<3];
struct Node
{
int dis,id;
Node(){}
Node(int dis,int id) : dis(dis), id(id){}
bool operator < (const Node& rhs) const
{
return dis>rhs.dis;
}
};
int dis[MAXN],b[MAXN],head[MAXN],num;
inline void add_edge(int from,int to,int dis)
{
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].dis=dis;
head[from]=num;
}
void Dijkstra(int s)
{
memset(dis,100,sizeof(dis));
priority_queue<Node> q;
q.push(Node(0,s));
while(!q.empty()){
Node u=q.top();q.pop();
if(b[u.id]) continue;
b[u.id]=1;
for(int i=head[u.id];i!=-1;i=edge[i].nxt){
int v=edge[i].to;
if(dis[v]>u.dis+edge[i].dis){
dis[v]=u.dis+edge[i].dis;
q.push(Node(dis[v],v));
}
}
}
}
int n,m,s,t;
int main()
{
cin>>n>>m;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++){
add_edge(i,i+1,1);
add_edge(i+1,i,1);
}
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
add_edge(x,x+y,0);
}
Dijkstra(0);
cout<<m-dis[m]<<endl;
}

I - 風船ツリー

题意:

给出一个有\(N\)个节点的气球树,以及每个气球到它父亲的边的长度。

现在给出\(Q\)组询问,每组询问询问使气球树的最大高度为\(H\)最少需要删掉多少条边。

分析:

思维巧妙的线段树题目,也不知道\(ATCODER\)啥时候能出出来这么NB的线段树题了。

思考删边的时候,每个子树会互相影响,所以并不能简单地一删了之。

观察发现询问明显不可以使用数据结构什么的东西维护,这东西并不具有结合性质。所以估计是预处理之后进行$O(1)回答。

当只有一组询问时,考虑做法,可以先找到这个深度的所有点,然后枚举那些是要留下来的,删去其连向儿子的边以及所有其他子树有深度大于\(x\)的边。并且可以发现并没有比这更优的做法。

那么是否可以对所有深度进行预处理,然后直接回答询问?

发现不同的深度最多只有\(N\)个,离散化一下,然后我们就能使用线段树对其进行维护了。

可以先\(dfs\)一下求出每个点向下连出的边的条数以及以它为根的子树到达的最大深度是多少,然后从\(1\)号点开始,对于我们进入的节点,删去其所有的儿子,具体是将其子树的深度一直到\(n\)都在线段树上打上标记,然后当遍历一个新的节点时,将这个节点添加回来,重复刚才的操作,这样就可以\(O(nlogn)\)求出对于任何一个深度,我们需要删掉多少条边,然后每次询问就可以\(O(logn)\)查询了。

#include <bits/stdc++.h>
#define mid (l+r>>1)
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int MAXN=1e5+7;
int add[MAXN<<2],n,m,sz,ll[MAXN],q;
inline void pushup(int rt)
{
add[rt]=add[ls]+add[rs];
}
inline void update(int l,int r,int rt,int x,int k)
{
if(l==r) add[rt]+=k;
else {
if(x<=mid) update(l,mid,ls,x,k);
else update(mid+1,r,rs,x,k);
pushup(rt);
}
}
inline int query(int L,int R,int l,int r,int rt)
{
int ans=0;
if(L<=l&&r<=R) return add[rt];
if(L<=mid) ans+=query(L,R,l,mid,ls);
if(R>mid) ans+=query(L,R,mid+1,r,rs);
return ans;
}
struct po
{
int nxt,to;
}edge[MAXN];
int head[MAXN],mx[MAXN],dep[MAXN],cnt[MAXN],dp[MAXN],num;
vector<int> vx;
inline void add_edge(int from,int to)
{
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
void dfs(int u,int fa)
{
mx[u]=dep[u];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v!=fa){
dfs(v,u);
mx[u]=max(mx[u],mx[v]);
}
}
}
inline void solve(int u,int fa)
{
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v!=fa) update(0,n+2,1,mx[v],1);
}
dp[dep[u]]=min(dp[dep[u]],query(dep[u]+1,vx.size()+1,0,n+2,1));
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa) continue;
update(0,n+2,1,mx[v],-1);
solve(v,u);
update(0,n+2,1,mx[v],1);
}
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v!=fa) update(0,n+2,1,mx[v],-1);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>ll[i];
dep[i]+=ll[i];
}
for(int i=2;i<=n;i++){
int p; cin>>p;
add_edge(p,i);
dep[i]+=dep[p];
vx.push_back(dep[i]);
} vx.push_back(dep[1]);
sort(vx.begin(),vx.end());
vx.erase(unique(vx.begin(),vx.end()),vx.end());
for(int i=1;i<=n;i++) dep[i]=lower_bound(vx.begin(),vx.end(),dep[i])-vx.begin(); for(int i=0;i<vx.size();i++) dp[i]=n;
dfs(1,1);
solve(1,1);
cin>>q;
for(int i=1;i<=q;i++){
int h;
cin>>h;
int pos=lower_bound(vx.begin(),vx.end(),h)-vx.begin();
if(pos==vx.size()||vx[pos]!=h) puts("-1");
else cout<<dp[pos]<<endl;
}
return 0;
}

CODE FESTIVAL 2015 決勝(部分)的更多相关文章

  1. 【赛时总结】 ◇赛时·IV◇ CODE FESTIVAL 2017 Final

    ◇赛时-IV◇ CODE FESTIVAL 2017 Final □唠叨□ ①--浓浓的 Festival 气氛 ②看到这个比赛比较特别,我就看了一看--看到粉粉的界面突然开心,所以就做了一下 `(* ...

  2. 【AtCoder】CODE FESTIVAL 2016 qual A

    CODE FESTIVAL 2016 qual A A - CODEFESTIVAL 2016 -- #include <bits/stdc++.h> #define fi first # ...

  3. 【AtCoder】CODE FESTIVAL 2016 qual B

    CODE FESTIVAL 2016 qual B A - Signboard -- #include <bits/stdc++.h> #define fi first #define s ...

  4. 【AtCoder】CODE FESTIVAL 2016 qual C

    CODE FESTIVAL 2016 qual C A - CF -- #include <bits/stdc++.h> #define fi first #define se secon ...

  5. CODE FESTIVAL 2017 qual B B - Problem Set【水题,stl map】

    CODE FESTIVAL 2017 qual B B - Problem Set 确实水题,但当时没想到map,用sort后逐个比较解决的,感觉麻烦些,虽然效率高很多.map确实好写点. 用map: ...

  6. CODE FESTIVAL 2017 qual B C - 3 Steps【二分图】

    CODE FESTIVAL 2017 qual B C - 3 Steps 题意:给定一个n个结点m条边的无向图,若两点间走三步可以到,那么两点间可以直接连一条边,已经有边的不能连,问一共最多能连多少 ...

  7. [AtCoder Code Festival 2017 QualB D/At3575] 101 to 010 - dp

    [Atcoder Code Festival 2017 QualB/At3575] 101 to 010 有一个01序列,每次可以选出一个101,使其变成010,问最优策略下能操作几次? 考虑像 11 ...

  8. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

  9. CODE FESTIVAL 2017 qual B

    昨晚因为有点事就去忙了,没打后悔啊 A - XXFESTIVAL Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem ...

随机推荐

  1. html5 canvas 详细使用教程 转

     分类: html5(9)  原文地址:http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html 原作很强悍 导航 前言 基本知识 绘 ...

  2. oninput事件(解决onkeyup无法监听到复制黏贴)

    change事件需要两个条件触发: a)当前对象属性改变,并且是由键盘或鼠标事件激发的(脚本触发无效) b)当前对象失去焦点(onblur)  keypress  能监听键盘事件,但鼠标复制黏贴操作就 ...

  3. Java获取当前服务器IP

    package hope.ipaddress.demo; import java.net.InetAddress; import java.net.NetworkInterface; import j ...

  4. php 代替 js实现自定义时间选择器

    w 0-php来结合服务端数据,处理前端页面的交互: 1-php 加法 乘法的效率对比,对算术运算的优化. 减少乘法运算? function w_select($wname, $wii) { $w = ...

  5. Python WSGI v1.0 中文版(转)

    add by zhj: WSGI全称Web Server Gateway Interface,即Web网关接口.其实它并不是OSI七层协议中的协议,它就是一个接口而已,即函数,而WSGI规定了该接口的 ...

  6. Django之html-模板继承

    在编程的过程中,我们经常会重复性的写了很多的代码,比如一个页面的框架部分,这样我又多少个页面就得写上多少次,这样既不好维护,也不够高效,所以我们引出了html的模板继承部分. 1.写好一个html文件 ...

  7. mysql分组取每组前几条记录(排名)

    1.创建表 create table tb( name varchar(10), val int, memo varchar(20) ); 2.插入数据 insert into tb values(' ...

  8. Python基础教程-List和Tuple

    List Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如: >>> classmates = ['Michael',' ...

  9. 利用VMware克隆linux虚拟机需要注意的事项

    利用VMware克隆虚拟机需要注意的问题 2018年03月30日 18:20:29 温文尔雅的流氓 阅读数:1343更多 个人分类: linux   版权声明:本文为博主原创文章,未经博主允许不得转载 ...

  10. 微信读书App来了 小伙伴们快去占榜吧

    微信读书App正式上线了,iOS版和Android版同时推出.届时将会出现像微信运动一样的霸榜小伙伴.资料显示,阅文集团成立于2014年1月,是腾讯文学和盛大文学联合成立的新公司.阅文集团成立后,会对 ...