码迷,mamicode.com
首页 > 其他好文 > 详细

【codeforces #300】EF题解

时间:2015-04-28 14:14:24      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:codeforecs   oi   dp   思路题   树状数组   

E. Demiurges Play Again

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Demiurges Shambambukli and Mazukta love to watch the games of ordinary people. Today, they noticed two men who play the following game.

There is a rooted tree on n nodes, m of which are leaves (a leaf is a nodes that does not have any children), edges of the tree are directed from parent to children. In the leaves of the tree integers from 1 to m are placed in such a way that each number appears exactly in one leaf.

Initially, the root of the tree contains a piece. Two players move this piece in turns, during a move a player moves the piece from its current nodes to one of its children; if the player can not make a move, the game ends immediately. The result of the game is the number placed in the leaf where a piece has completed its movement. The player who makes the first move tries to maximize the result of the game and the second player, on the contrary, tries to minimize the result. We can assume that both players move optimally well.

Demiurges are omnipotent, so before the game they can arbitrarily rearrange the numbers placed in the leaves. Shambambukli wants to rearrange numbers so that the result of the game when both players play optimally well is as large as possible, and Mazukta wants the result to be as small as possible. What will be the outcome of the game, if the numbers are rearranged by Shambambukli, and what will it be if the numbers are rearranged by Mazukta? Of course, the Demiurges choose the best possible option of arranging numbers.

Input
The first line contains a single integer n — the number of nodes in the tree (1?≤?n?≤?2·105).

Each of the next n?-?1 lines contains two integers ui and vi (1?≤?ui,?vi?≤?n) — the ends of the edge of the tree; the edge leads from node ui to node vi. It is guaranteed that the described graph is a rooted tree, and the root is the node 1.

Output
Print two space-separated integers — the maximum possible and the minimum possible result of the game.

Sample test(s)
input
5
1 2
1 3
2 4
2 5
output
3 2
input
6
1 2
1 3
3 4
1 5
5 6
output
3 3
Note
Consider the first sample. The tree contains three leaves: 3, 4 and 5. If we put the maximum number 3 at node 3, then the first player moves there and the result will be 3. On the other hand, it is easy to see that for any rearrangement the first player can guarantee the result of at least 2.

In the second sample no matter what the arragment is the first player can go along the path that ends with a leaf with number 3.

dp

对于以i为根的子树的叶子,我们只考虑他在这棵子树的叶子中的rank。

f[i]=k表示在i最终会走到以i为根的子树中第k小的叶子上。

一.想让答案尽可能小:
①若当前是先手,他想让答案尽可能大,那么只要把所有儿子yf[y]相加就是结果。因为f[y]表示rank,一个rank只能属于一个叶子,所以自然是相加了

②如果当前是后手,他想让答案尽可能小,那么答案就是min(f[y])

二.想让答案尽可能大:
f[i]=k定义为第k大。
①先手让答案尽可能大,就是min(f[y])

②后手让答案尽可能小,就是f[y]相加

把两个合在一起写就好了。

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct edge
{
    int y,ne;
}e[500005];
int tot,h[200005],n;
void Addedge(int x,int y)
{
    e[++tot].y=y;
    e[tot].ne=h[x];
    h[x]=tot;
}
int dfs(int x,int k)
{
    if (!h[x]) return 1;
    int  t1=500000,t2=0;
    for (int i=h[x];i;i=e[i].ne)
        if (k) t2+=dfs(e[i].y,k^1);
        else t1=min(t1,dfs(e[i].y,k^1));
    if (k) return t2;
    return t1;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        Addedge(x,y);
    }
    int l=0;
    for (int i=1;i<=n;i++)
        if (!h[i]) l++;
    cout<<l+1-dfs(1,0)<<" "<<dfs(1,1)<<endl;
    return 0;
}

F. A Heap of Heaps

time limit per test3 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
Andrew skipped lessons on the subject ‘Algorithms and Data Structures’ for the entire term. When he came to the final test, the teacher decided to give him a difficult task as a punishment.

The teacher gave Andrew an array of n numbers a1, …, an. After that he asked Andrew for each k from 1 to n?-?1 to build a k-ary heap on the array and count the number of elements for which the property of the minimum-rooted heap is violated, i.e. the value of an element is less than the value of its parent.

Andrew looked up on the Wikipedia that a k-ary heap is a rooted tree with vertices in elements of the array. If the elements of the array are indexed from 1 to n, then the children of element v are elements with indices k(v?-?1)?+?2, …, kv?+?1 (if some of these elements lie outside the borders of the array, the corresponding children are absent). In any k-ary heap every element except for the first one has exactly one parent; for the element 1 the parent is absent (this element is the root of the heap). Denote p(v) as the number of the parent of the element with the number v. Let’s say that for a non-root element v the property of the heap is violated if av?<?ap(v).

Help Andrew cope with the task!

Input
The first line contains a single integer n (2?≤?n?≤?2·105).

The second line contains n space-separated integers a1, …, an (?-?109?≤?ai?≤?109).

Output
in a single line print n?-?1 integers, separate the consecutive numbers with a single space — the number of elements for which the property of the k-ary heap is violated, for k?=?1, 2, …, n?-?1.

Sample test(s)
input
5
1 5 4 3 2
output
3 2 1 0
input
6
2 2 2 2 2 2
output
0 0 0 0 0

思路题+树状数组。

k-ary heap中,i的儿子是k?(i?1)+2k?i+1这一段区间。

那么i有儿子的k的取值大约有ni?1中,对于每一个i都枚举k,复杂度是O(nlogn)的。

我们对原数组排序,从小到大加入树状数组,每次枚举k,统计儿子中比他小的个数即可。

注意,对于数值相同的情况,把位置靠前的放在前面即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
int t[200005],ans[200005],n;
struct data
{
    int id,v;
}a[200005];
bool cmp(data a,data b)
{
    if (a.v==b.v) return a.id<b.id;
    return a.v<b.v;
}
int lowbit(int x)
{
    return x&(-x);
}
void Update(int x)
{
    for (int i=x;i<=n;i+=lowbit(i))
        t[i]++;
}
int Getsum(int x)
{
    int ans=0;
    for (int i=x;i;i-=lowbit(i))
        ans+=t[i];
    return ans;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i].v),a[i].id=i;
    sort(a+1,a+1+n,cmp);
    for (int i=1;i<=n;i++)
    {
        int p=a[i].id;
        for (int k=1;k*(p-1)+2<=n&&k<n;k++)
        {
            int l=k*(p-1)+2,r=min(n,k*p+1);
            ans[k]+=(Getsum(r)-Getsum(l-1));
        }
        Update(p);
    }
    for (int i=1;i<n-1;i++)
        printf("%d ",ans[i]);
    printf("%d\n",ans[n-1]);
    return 0;
}

【codeforces #300】EF题解

标签:codeforecs   oi   dp   思路题   树状数组   

原文地址:http://blog.csdn.net/regina8023/article/details/45334321

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!