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);
}