Codeforces #245(div2)

果7發表於2014-05-13

A:A. Points and Segments (easy)

題目看了n久,開始覺得尼瑪這是div2的題目麼,題目還標明瞭easy。。
意思是給你一n個點,m個區間,在n個點上放藍球或者紅球,然後讓你找一種選擇方案使得m個區間內的藍球和紅球數量之差不超過1.
開始想過用dfs,不過這只是div2的A題而已。。


然後想了下,直接輸出010101序列不就可以麼。

交了一發,發現要先排個序,再輸出就可以了。

AC程式碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int res[150];

struct node
{
    int x,id;
}nod[150];

bool cmp(node a,node b)
{
    return a.x<b.x;
}

int main()
{
    int i,n,m;
    int a,b;

    while(~scanf("%d%d",&n,&m))
    {
        for(i=0;i<n;i++)
            scanf("%d",&nod[i].x),nod[i].id=i;
        for(i=0;i<m;i++)
            scanf("%d%d",&a,&b);
        sort(nod,nod+n,cmp);

        int t=0;
        for(i=0;i<n;i++)
            res[nod[i].id]=(++t)%2;

        printf("%d",res[0]);
        for(i=1;i<n;i++)
            printf(" %d",res[i]);
        printf("\n");
    }
    return 0;
}

B:B. Balls Game

題目大意:給你n個球,然後最多k個種類,同類的挨在一起同類的超過三個的可以抵消。開始的n個沒有抵消的情況,問給你一個顏色為x的球,問你用這個球insert進去最多能消掉n個球裡面的個數。

直接模擬就好,不過,自己被自己坑了好久。。


AC程式碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
using namespace std;

int a[105];

int main()
{
    int n,k,x;

    int i;
    while(cin>>n>>k>>x)
    {
        int res=0;
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);

        for(i=1;i<=n;i++)
        {
            int ans=0,t1,t2;
            if(a[i]==x&&i+1<=n&&a[i+1]==x)
            {
                ans+=2;
                t1=i-1,t2=i+2;

                while(t1>=1&&t2<=n)
                {
                    int cnt=0;
                    int x=a[t1];
                    while(a[t2]==x&&t2<=n)
                    {
                        cnt++;
                        t2++;
                    }
                    while(a[t1]==x&&t1>=1)
                    {
                        cnt++;
                        t1--;
                    }
                    if(cnt<3) break;
                    else ans+=cnt;
                }
                res=max(res,ans);
            }
        }

        cout<<res<<endl;
    }
    return 0;
}
/*
10 2 2
2 2 1 1 2 2 1 1 2 2
*/


C. Xor-tree
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Iahub is very proud of his recent discovery, propagating trees. Right now, he invented a new tree, called xor-tree. After this new revolutionary discovery, he invented a game for kids which uses xor-trees.

The game is played on a tree having n nodes, numbered from 1 to n. Each node i has an initial value initi, which is either 0 or 1. The root of the tree is node 1.

One can perform several (possibly, zero) operations on the tree during the game. The only available type of operation is to pick a nodex. Right after someone has picked node x, the value of node x flips, the values of sons of x remain the same, the values of sons of sons of x flips, the values of sons of sons of sons of x remain the same and so on.

The goal of the game is to get each node i to have value goali, which can also be only 0 or 1. You need to reach the goal of the game by using minimum number of operations.

Input

The first line contains an integer n (1 ≤ n ≤ 105). Each of the next n - 1 lines contains two integers ui and vi (1 ≤ ui, vi ≤ nui ≠ vi) meaning there is an edge between nodes ui and vi.

The next line contains n integer numbers, the i-th of them corresponds to initi (initi is either 0 or 1). The following line also contains ninteger numbers, the i-th number corresponds to goali (goali is either 0 or 1).

Output

In the first line output an integer number cnt, representing the minimal number of operations you perform. Each of the next cnt lines should contain an integer xi, representing that you pick a node xi.

Sample test(s)
input
10
2 1
3 1
4 2
5 1
6 2
7 5
8 6
9 8
10 5
1 0 1 1 0 1 0 1 0 1
1 0 1 0 0 1 1 1 0 1
output
2
4
7


題目大意:給你一顆樹,給你所有節點的初始狀態,然後再給你一個需要轉變到的狀態,如果一個節點的狀態發生改變,那麼他的兒子節點不變^0,他的兒子的兒子節點^1,他兒子的兒子的兒子。。找最小的次數。

直接從根,(題目說了根是1)往下dfs,即可。


AC程式碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100005;

vector <int> mq[maxn];

int sta[maxn],en[maxn];
int res[maxn];
int cnt;

void dfs(int cur,int fa,int u,int v)
{
    int flag=0;
    sta[cur]^=v;
    if(sta[cur]!=en[cur])
    {
        flag=1;
        res[cnt++]=cur;
    }
    v=flag^v;

    for(int i=0;i<mq[cur].size();i++)
    {
        int nex=mq[cur][i];
        if(nex!=fa)
        {
            dfs(nex,cur,v,u);
        }
    }
}

int main()
{
    int n,i;

    while(cin>>n)
    {
        cnt=0;
        int u,v;
        for(i=1;i<=n;i++)
            mq[i].clear();
        for(i=1;i<n;i++)
        {
            cin>>u>>v;
            mq[u].push_back(v);
            mq[v].push_back(u);
        }

        for(i=1;i<=n;i++) cin>>sta[i];
        for(i=1;i<=n;i++) cin>>en[i];
        dfs(1,0,0,0);

        cout<<cnt<<endl;
        for(i=0;i<cnt;i++)
            cout<<res[i]<<endl;
    }

    return 0;
}

/*
10
2 1
3 1
4 2
5 1
6 2
7 5
8 6
9 8
10 5
1 0 1 1 0 1 0 1 0 1
1 0 1 0 0 1 1 1 0 1
*/


D:D. Working out


題目大意:一個n*m的格子,一個人從(1,1)走到(n,m),一個人從(n,1)走到(1,m),他們速度不同,必須有一個交點,在那個交點那裡的分數不算,其他兩個人走過的格子分數都只算一次,問最大得多少分。第一個人只能往右下方向走,第二個人只能往右上方向走。


解題思路:我們需要列舉他們的交點,然後判定情況。需要記錄來的方向,dp,先四次dp預處理,然後找最大值。詳見圖片與程式碼。





可以思考下,只有這兩種情況,不然就會重疊,而重疊的只算一次的。

AC程式碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
using namespace std;

int dp[4][1005][1005];
int a[1005][1005];
int n,m;

void solve()
{
    int i,j;
    for(i=1; i<=n; i++)   //左上
        for(j=1; j<=m; j++)
            dp[0][i][j] = max(dp[0][i-1][j],dp[0][i][j-1]) + a[i][j];

    for(i=1; i<=n; i++)   //右上
        for(j=m; j>=1; j--)
            dp[1][i][j] = max(dp[1][i-1][j],dp[1][i][j+1]) + a[i][j];

    for(i=n; i>=1; i--)   //左下
        for(j=1; j<=m; j++)
            dp[2][i][j] = max(dp[2][i][j-1],dp[2][i+1][j]) + a[i][j];

    for(i=n; i>=1; i--)   //右下
        for(j=m;j>=1; j--)
            dp[3][i][j] = max(dp[3][i][j+1],dp[3][i+1][j]) + a[i][j];
}

int main()
{
    int i,j;

    memset(dp,0,sizeof(dp));
    while(cin>>n>>m)
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                scanf("%d",&a[i][j]);

        solve();
        int res = 0;
        for(i=2; i<n; i++)
            for(j=2; j<m; j++)
            {
                int t1,t2;
                t1=dp[0][i-1][j]+dp[3][i+1][j]+dp[1][i][j+1]+dp[2][i][j-1];
                t2=dp[0][i][j-1]+dp[3][i][j+1]+dp[1][i-1][j]+dp[2][i+1][j];
                //cout<<t1<<" "<<t2<<endl;
                res=max(res,max(t1,t2));
            }

        printf("%d\n",res);
    }
    return 0;
}

/*
3 3
100 100 100
100 1 100
100 100 100
*/


E題,DFS不知如何下手。

相關文章