首页 > 代码库 > Codeforces_812

Codeforces_812

A. 每条人行道有六条车道会撞到。

技术分享
#include<bits/stdc++.h>
using namespace std;

int a[4],b[4],c[4],d[4];

int main()
{
    ios::sync_with_stdio(0);
    for(int i = 0;i < 4;i++)    cin >> a[i] >> b[i] >> c[i] >> d[i];
    int flag = 0;
    for(int i = 0;i < 4;i++)
    {
        if(!d[i])   continue;
        if(a[i] || b[i] || c[i] || a[(i+1)%4] || b[(i+2)%4] || c[(i+3)%4])  flag = 1;
    }
    if(flag)    cout << "YES" << endl;
    else    cout << "NO" << endl;
    return 0;
}
View Code

B.dp,注意最后一层增加的时间不一样。

技术分享
#include<bits/stdc++.h>
using namespace std;

int n,m,dp[2][20] = {0};
string s[20];

int main()
{
    ios::sync_with_stdio(0);
    cin >> n >> m;
    for(int i = 1;i <= n;i++)
    {
        cin >> s[i];
        s[i] = " "+s[i];
    }
    int t;
    for(t = 1;t <= n;t++)
    {
        int flag = 0;
        for(int j = 1;j <= m+2;j++)
        {
            if(s[t][j] == 1)  flag = 1;
        }
        if(flag)    break;
    }
    if(t == n+1)
    {
        cout << 0 << endl;
        return 0;
    }
    dp[0][n+1] = -1;
    dp[1][n+1] = 1e9;
    for(int i = n;i >= t;i--)
    {
        int l = m+2;
        int r = 1;
        for(int j = m+2;j >= 1;j--)
        {
            if(s[i][j] == 1)  l = j;
        }
        for(int j = 1;j <= m+2;j++)
        {
            if(s[i][j] == 1)  r = j;
        }
        if(i == t)
        {
            cout << min(dp[0][i+1]+r,dp[1][i+1]+m+3-l) << endl;
            return 0;
        }
        dp[0][i] = min(dp[1][i+1]+m+2,dp[0][i+1]+2*(r-1)+1);
        dp[1][i] = min(dp[0][i+1]+m+2,dp[1][i+1]+2*(m+2-l)+1);
    }
    return 0;
}
View Code

C.二分个数,注意long long。

技术分享
#include<bits/stdc++.h>
using namespace std;

int n,s;
long long a[100005],b[100005];

bool ok(int x)
{
    for(int i = 1;i <= n;i++)   b[i] = a[i]+(long long)x*i;
    sort(b+1,b+1+n);
    long long sum = 0;
    for(int i = 1;i <= x;i++)   sum += b[i];
    return sum <= s;
}
int main()
{
    ios::sync_with_stdio(0);
    cin >> n >> s;
    for(int i = 1;i <= n;i++)   cin >> a[i];
    int l = 0,r = n;
    while(l < r)
    {
        int mid = (l+r+1)/2;
        if(ok(mid)) l = mid;
        else    r = mid-1;
    }
    for(int i = 1;i <= n;i++)   b[i] = a[i]+(long long)l*i;
    sort(b+1,b+1+n);
    long long sum = 0;
    for(int i = 1;i <= l;i++)   sum += b[i];
    cout << l << " " << sum << endl;
    return 0;
}
View Code

D.建一个有向图,前面的requests组成的是森林或树,再加一个后,若形成了环,则x和x的子孙都会cry,否则没有人会cry。

对于1e5的queries,我们先预处理每个节点的子孙个数和和dfs序,然后判断就简单了。

技术分享
#include<bits/stdc++.h>
using namespace std;

int n,m,k,q,cnt = 0,pre[100005] = {0},l[100005],r[100005],ok[100005] = {0},sum[100005];
vector<int> v[100005];

void dfs(int now)
{
    ++cnt;
    l[now] = cnt;
    sum[now] = 1;
    for(int i = 0;i < v[now].size();i++)
    {
        int t = v[now][i];
        dfs(t);
        sum[now] += sum[t];
    }
    r[now] = cnt;
}
int main()
{
    ios::sync_with_stdio(0);
    cin >> n >> m >> k >> q;
    while(k--)
    {
        int x,y;
        cin >> x >> y;
        if(pre[y] != 0)
        {
            v[pre[y]].push_back(x);
            ok[x] = 1;
        }
        pre[y] = x;
    }
    for(int i = 1;i <= n;i++)
    {
        if(!ok[i])  dfs(i);
    }
    while(q--)
    {
        int x,y;
        cin >> x >> y;
        if(pre[y] && l[x] <= l[pre[y]] && r[pre[y]] <= r[x])    cout << sum[x] << endl;
        else    cout << 0 << endl;
    }
    return 0;
}
View Code

E.普通nim游戏判断过程为每堆石子个数的异或。若增加一个可以增加石子的操作,结果相同,因为一个人加的另一个人可以减去相同数量。我们建树,把跟叶子节点向上相差偶数个节点的点作为堆,其余的作为可以增加的石子。那么判断过程为这些堆的异或。ok为0则成立,我们现在要使ok变为0。

根据异或性质,在两类节点之间可以成立的交换操作为ok^a[i]^b[i]==0的两个点。

另外,若ok已经为0,我们可以进行节点同类中交换。

技术分享
#include<bits/stdc++.h>
using namespace std;

int n,a[200005],h[200005];
map<int,int> mp;
vector<int> v[200005];

void dfs(int now)
{
    int x = 0;
    for(int i = 0;i < v[now].size();i++)
    {
        int t = v[now][i];
        dfs(t);
        x = max(h[t],x);
    }
    h[now] = x+1;
}

int main()
{
    ios::sync_with_stdio(0);
    cin >> n;
    for(int i = 1;i <= n;i++)   cin >> a[i];
    for(int i = 2;i <= n;i++)
    {
        int x;
        cin >> x;
        v[x].push_back(i);
    }
    dfs(1);
    int ok = 0,cnt1 = 0;
    for(int i = 1;i <= n;i++)
    {
        if(h[i]%2)
        {
            ok ^= a[i];
            cnt1++;
            mp[a[i]]++;
        }
    }
    int cnt2 = n-cnt1;
    long long ans = 0;
    if(ok == 0) ans = (long long)cnt1*(cnt1-1)/2+(long long)cnt2*(cnt2-1)/2;
    for(int i = 1;i <= n;i++)
    {
        if(h[i]%2 == 0) ans += mp[ok^a[i]];
    }
    cout << ans << endl;
    return 0;
}
View Code

 

Codeforces_812