Codeforces 981 共同点路径覆盖树构造 BFS/DP书架&最大值

A

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7;
const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int N = 2e5 + 5;
bool ok(string x)
{
        int len = x.size();
        if (len == 1)
        {
                return true;
        }
        for (int i = 0; i < x.size() / 2; i++)
        {
                if (x[i] != x[x.size() - 1 - i])
                {
                        return false;
                }
        }
        return true;
}
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        string a;
        cin >> a;
        int flag = 1;
        while (flag)
        {
                if (ok(a))
                {
                        if (a.size() == 1)
                        {
                                cout << 0 << endl;
                                return 0;
                        }
                        a = a.substr(0, a.size() - 1);
                }
                else
                {
                        flag = 0;
                }
        }
        cout << a.size() << endl;
        return 0;
}
View Code

B

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7;
const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int N = 2e5 + 5;
map<int,ll> mp;
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        ll anser=0;
        int n,m;
        cin >> n;
        int a,b;
        for(int i=1;i<=n;i++)
        {
                cin >> a >> b;
                if(mp[a]<b)
                {
                        anser+=b-mp[a];
                        mp[a]=b;
                }
        }
        cin >> m;
        for(int i=1;i<=m;i++)
        {
                cin >> a >> b;
                if(mp[a]<b)
                {
                        anser+=b-mp[a];
                        mp[a]=b;
                }
        }
        cout<<anser<<endl;
        return 0;
}
View Code

C

解:

构造题

很明显如果是有不小于一个的度大于2的点则No

如果没有度大于2的点则是一条链 直接输出两端 如果有的话则是菊花图 找每个度为1的叶子点与中心相连

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7;
const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int N = 1e5 + 5;
vector<int> g[N];
int du[N];
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        int n;
        cin >> n;
        int u, v;
        for (int i = 1; i < n; i++)
        {
                cin >> u >> v;
                g[u].pb(v), g[v].pb(u);
                du[u]++, du[v]++;
        }
        int sum = 0;
        int maxn = -1;
        int aim = 0;
        for (int i = 1; i <= n; i++)
        {
                if (du[i] > 2)
                {
                        sum++;
                }
                if (du[i] > maxn)
                {
                        aim = i;
                        maxn = du[i];
                }
        }
        if (sum > 1)
        {
                cout << "No" << endl;
                return 0;
        }
        if (maxn > 2)
        {
                cout << "Yes" << endl;
                int cnt=0;
                for(int i=1;i<=n;i++)
                {
                        if(du[i]==1)
                        {
                                cnt++;
                        }
                }
                cout << cnt << endl;
                for (int i = 1; i <= n; i++)
                {
                        if (i == aim)
                        {
                                continue;
                        }
                        if (du[i] == 1)
                        {
                                cout << aim << " " << i << endl;
                        }
                }
        }
        else
        {
                cout << "Yes" << endl;
                cout << 1 << endl;
                for (int i = 1; i <= n; i++)
                {
                        if (du[i] == 1)
                        {
                                cout << i << " ";
                        }
                }
                cout << endl;
        }
        return 0;
}
View Code

D. Bookshelves

题意:

给你N个书K个书架,每个书有一个价值,要求你把书分成 连续的K段 分配进这K个书架使得这几个书架的总值 AND值 最大

解:

贪心 DP或者BFS

首先因为是AND操作所以我们要从最高位开始贪心 如果可行的话就 ans | =1 << i

DP:

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7;
const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int N = 55 + 5;
int n, K;
ll sum[N][N];
ll a[N];
bool dp[N][N];
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cin >> n >> K;
        for (int i = 1; i <= n; i++)
        {
                cin >> a[i];
                sum[i][i] = a[i];
                for (int j = i - 1; j >= 1; j--)
                {
                        sum[j][i] = sum[j + 1][i] + a[j];
                }
        }
        //sum[i][j]表示从第i位到第j位的前缀和
        ll ans = 0;
        for (int w = 60; w >= 0; w--)  //从最高位开始贪起
        {
                mem(dp, 0); //每一次要初始化
                dp[0][0] = 1;  //dp[i][j]表示把前N个数分成j块每块都有 1<<w 是否可以
                for (int i = 1; i <= n; i++)
                {
                        for (int j = i - 1; j >= 0; j--)
                        {
                                for (int k = 1; k <= K; k++)
                                {
                                        //如果从前的位置j满足可以分为k-1块而且从j+1到i的前缀和包含了之前贪心的答案同时1<<w位为1
                                        if (dp[j][k - 1] && (sum[j + 1][i]&ans) == ans && ((sum[j + 1][i] >> w) & 1))
                                        {
                                                dp[i][k] = 1;
                                        }
                                }
                        }
                }
                if (dp[n][K])
                {
                        ans |= 1LL << w;
                }
        }
        cout << ans << endl;
        return 0;
}
View Code

BFS

E. Addition on Segments

 

posted @ 2018-05-29 17:07  Aragaki  阅读(195)  评论(0编辑  收藏  举报