Codeforces Round #480 (Div. 2)题解

C - Posterized

混沌的贪心。

从左往右遍历一遍,对于位置i,如果a[i]的分组被确定了,那么我们直接输出它所在的分组,否则我们从a[i]开始,递减往下找,设找到的第一个元素为x,如果x所在的Group能容得下a[i],那就容纳下a[i],将[x+1,a[i]]都和y分到一组。否则将[x+1,a[i]]分成一组。

#include <iostream>
#include <cstring>
using namespace std;
const int N = 200000+10;

int n,k,a[N];
int group[N], size[N];
int main() {
    scanf("%d%d",&n,&k);
    memset(group,-1,sizeof(group));
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        if (group[a[i]] != -1) {
            printf("%d ", group[a[i]]);
            continue;
        }

        int x=a[i];
        while(x>=0 && a[i]-x+1<=k && group[x]==-1) x--;
        // not exist
        if(x < 0 || group[x] == -1) {
            x ++;
            for(int j=x;j<=a[i];j++) 
                group[j] = x, size[x] ++;
            printf("%d ", x);
            continue;
        }

        int cnt=a[i]-x;
        if(size[group[x]]+cnt<=k) { // can join
            for(int j=x+1;j<=a[i];j++)
                group[j]=group[x], size[group[x]]++;
            printf("%d ", group[x]);
        } else {                    // can not join
            for(int j=x+1;j<=a[i];j++)
                group[j]=x+1, size[x+1] ++;
            printf("%d ", x+1);
        }
    }
}

D - Perfect Groups

对每个数字进行分解质因数,指数为偶数的质因子扔掉,指数为奇数的质因子应该保留。如果两个数字保留下的数字的集合相等,那么乘起来就会得到一个完全平方数。集合相等的判定,根据唯一因子分解定理,只需集合内元素乘起来相等。【显然,喵!】

注意几点:

  • 离散化的预处理
  • 0的处理【FST的喜悦】

E - The Number Games

以n为根进行DFS,预处理每个节点深度。从大到小尝试着保留每一个节点。

求每个点加入进来的耗费,有两种方法。

  • 倍增,从当前枚举的节点,一直往上面跳,跳到我们保留的的节点就打住。
  • 预处理DFS序,用线段树维护:一个节点,一直往上跳,会遇到的第一个保留节点的深度。

姿势1

#include <iostream>
#include <vector>
using namespace std;
const int N = 1000000 + 10;
vector<int> g[N];
int dep[N], par[N][22];
int n, k;
int mark[N];

void dfs(int u, int p) {
    par[u][0] = p;
    for(int i=1;i<21;i++)
        par[u][i] = par[par[u][i-1]][i-1];

    for(int i=0;i<g[u].size();i++) {
        int v = g[u][i];
        if (v == p) continue;
        dep[v] = dep[u] + 1;
        dfs(v, u);
    }
}

int main() {
    scanf("%d %d",&n,&k);
    for(int i=1;i<n;i++) {
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    dfs(n, n);
    mark[n] = 1;
    int cnt = 1;
    for (int i = n-1; i >= 1; i --) {
        if (mark[i]) continue;
        int now = i;
        for (int j = 20; j >= 0; j --) {
            if (mark[par[now][j]] == 0)
                now = par[now][j];
        }
        now = par[now][0];

        if (cnt + dep[i] - dep[now] <= n - k) {
            cnt = cnt + dep[i] - dep[now];
            int paiGuLong = i;
            while (paiGuLong != now) {
                mark[paiGuLong] = 1;
                paiGuLong = par[paiGuLong][0];
            }
        }
    }

    for (int i=1;i<=n;i++)
        if (mark[i]==0)
            printf("%d ", i);
}



posted @ 2018-05-09 22:16  RUSH_D_CAT  阅读(155)  评论(0编辑  收藏  举报