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. POJO应用框架:Spring与EJB3.0的比较

    英文原文地址:http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html中文地址:http://www.matrix.org.cn/r ...

  2. Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

    在上面一个章节中,详细的讲解了Kotlin中关于Lambda表达式的语法以及运用,如果还您对其还不甚理解,请参见Kotlin--高级篇(一):Lambda表达式详解.在这篇文章中,多次提到了Kotli ...

  3. 离散化——化不可能为可能(STL)

    所谓离散,就是化连续为不连续,使得我们某种枚举的方法得以实现. 当然,离散还能够帮助我们将某些数据范围很大达到2^16,但是这些数据并不多(例如才1000+),我们可以把数据进行离散,保持他们之间的相 ...

  4. VS2013\VS2017 使用git 总是需要输入账号密码

    问题: VS2013\VS2017 使用git 总是需要输入账号密码 解决方案:删除原凭证,或者修改原凭证,重新输入一次账号和密码并且选择“记住凭证”即可!

  5. 【BZOJ4560】[JLoi2016]字符串覆盖 KMP+状压DP

    [BZOJ4560][JLoi2016]字符串覆盖 Description 字符串A有N个子串B1,B2,…,Bn.如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠)这样A中的若 ...

  6. iOS 程序切换后台

    1. -(void)animationFinished:(NSString*)animationid finished:(NSNumber*)finished context:(void*)conte ...

  7. Leetcode-Permuation Sequence

    The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  8. ZOJ 3332 Strange Country II

    Strange Country II Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge You want to v ...

  9. tortoisegit错误: disconnected - no supported authentication methods available(server sent: publickey)

    修改小乌龟的 SSH客户端:

  10. Java 常用语法和数据结构

    Collection 首先Java中的collection都是支持泛型和类型安全 由于Java单根继承, 所以不指定, 可以在collection里面放任何对象, collection会都当作obje ...