【AtCoder】ARC086
C - Not so Diverse
题解
选出现次数K多的出来,剩下的都删除即可
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,K;
int A[MAXN],cnt[MAXN],val[MAXN],tot;
bool cmp(int a,int b) {
return a > b;
}
void Init() {
read(N);read(K);
for(int i = 1 ; i <= N ; ++i) {
read(A[i]);
cnt[A[i]]++;
}
}
void Solve() {
for(int i = 1 ; i <= N ; ++i) {
if(cnt[i]) val[++tot] = cnt[i];
}
sort(val + 1,val + tot + 1,cmp);
int ans = 0;
for(int i = K + 1 ; i <= tot ; ++i) ans += val[i];
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}
D - Non-decreasing
题解
用N - 1次操作把序列变成全正或者全负
如果全负用处理成后缀和
如果全正处理成前缀和
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N;
int a[MAXN];
vector<pii > op;
void Init() {
read(N);
for(int i = 1 ; i <= N ; ++i) read(a[i]);
}
void Solve() {
int t = 1;
for(int i = 2 ; i <= N ; ++i) {
if(abs(a[i]) > abs(a[t])) t = i;
}
for(int i = 1 ; i <= N ; ++i) {
if(i != t) {
op.pb(mp(t,i));
a[i] += a[t];
}
}
if(a[t] < 0) {
for(int i = N - 1 ; i >= 1 ; --i) {
a[i] += a[i + 1];
op.pb(mp(i + 1,i));
}
}
else {
for(int i = 2 ; i <= N ; ++i) {
a[i] += a[i - 1];
op.pb(mp(i - 1,i));
}
}
out(op.size());enter;
for(auto k : op) {
out(k.fi);space;out(k.se);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}
E - Smuggling Marbles
题解
这个如果我们每个深度从每个点往上更新,更新的时候把儿子只有一个的点缩掉就显然不会超过\(N \log N\),但是因为种种原因,在向上BFS的时候需要按深度从大到小排序
题解说有\(O(n)\)做法,我没细看
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N,ans;
int p[MAXN],dep[MAXN],pw[MAXN];
vector<int> lay[MAXN];
int vis[MAXN],tims,cnt[MAXN],dp[MAXN][2];
vector<int> son[MAXN];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void update(int &x,int y) {
x = inc(x,y);
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
void Init() {
read(N);
for(int i = 1 ; i <= N ; ++i) read(p[i]);
for(int i = 1 ; i <= N ; ++i) dep[i] = dep[p[i]] + 1;
for(int i = 1 ; i <= N ; ++i) {
lay[dep[i]].pb(i);
}
pw[0] = 1;
for(int i = 1 ; i <= N + 1 ; ++i) pw[i] = mul(pw[i - 1],2);
}
auto cmp = [](int a,int b){return dep[a] < dep[b];};
priority_queue<int, vector<int>, decltype(cmp)> Q(cmp);
void BFS() {
while(!Q.empty()) {
int u = Q.top();Q.pop();
if(vis[p[u]] != tims) {
Q.push(p[u]);
vis[p[u]] = tims;
son[p[u]].clear();
dp[p[u]][0] = dp[p[u]][1] = 0;
}
if(son[u].size() == 1){
if(u != 0) {
p[son[u][0]] = p[u];
son[p[u]].pb(son[u][0]);
}
}
else if(u != 0) son[p[u]].pb(u);
if(son[u].size() > 1 || u == 0) {
int s1 = 1,s2 = 1;
for(auto v : son[u]) {
s1 = mul(s1,dp[v][0]);
s2 = mul(s2,inc(dp[v][0],dp[v][1]));
}
for(auto v : son[u]) {
update(dp[u][1],mul(s1, mul(fpow(dp[v][0], MOD - 2), dp[v][1])));
}
dp[u][0] = inc(s2, MOD - dp[u][1]);
}
}
}
void Solve() {
update(ans,pw[N]);
for(int i = 1 ; i <= N ; ++i) {
if(!lay[i].size()) break;
++tims;
for(auto k : lay[i]) {
Q.push(k);vis[k] = tims;
dp[k][0] = 1;dp[k][1] = 1;
}
BFS();
update(ans,mul(dp[0][1], pw[N + 1 - lay[i].size()]));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
F - Shift and Decrement
题解
这题有点神仙啊QAQ
首先,如果我们把除二认为是小数,最后再取整,结果也不变
其次A操作进行最多60次就全0了
所以我们认为第0次和第1次A之前的B操作有\(p_0\)个,第1次和第2次A之前的B操作有\(p_1\)个,到最后一次第\(k\)的次数\(p_k\)定义类似
然后我们可以这么认为
进行了\(B\)操作使得所有数减少了\(P\)
\(P = \sum_{i = 0}^{k - 1} 2^{i}p_{k}\)
然后进行\(k\)次\(A\),并且取整
然后进行\(p_k\)次\(B\)
\(P\)可以在取模\(2^k\)下进行,变成一次第三个操作,可以节约前两次用的操作数
然后我们发现对于一个固定的\(k\),我们可以把每个数写成\(A_{i} = 2^{k}B_{i} + C_{i}\)
如果\(P > C_{i}\),这个数就是\(B_{i} - p_k -1\)
否则这个数就是\(B_{i} - p_k\)
所以我们按照余数大小排序,\(P\)在某个区间内是等价的
我们要尽可能使第三种操作取值范围大,就要使前两种操作用的操作小,当我枚举一个k时,第二种用的操作数固定,我要找到\(P\)所在的区间\([l,r]\)内二进制数位上1最少的数,可以用简单的数位dp实现
枚举k,根据\(P\)取值不同,我们可以得到最多\(61 * N\)个序列
只要求这些序列能减的最大值就行吗,不是的,有些序列通过相减会重复,我们需要把差分相同的序列分到一起
然后做一下区间求并即可
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N,tot;
int64 K,a[205],rk[205];
vector<pair<int64,int64> > range;
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
struct node {
int64 c[205],u;
friend bool operator == (const node &a,const node &b) {
for(int i = 2 ; i <= N ; ++i) {
if(a.c[i] != b.c[i]) return false;
}
return true;
}
friend bool operator < (const node &a,const node &b) {
for(int i = 2 ; i <= N ; ++i) {
if(a.c[i] != b.c[i]) return a.c[i] < b.c[i];
}
return false;
}
friend bool operator != (const node &a,const node &b) {
return !(a == b);
}
}seq[205 * 62];
int minpopcount(int64 l,int64 r) {
int dp[2][5];
int cur = 0;
for(int i = 0 ; i <= 3 ; ++i) dp[cur][i] = 1000000;
dp[cur][3] = 0;
for(int i = 60 ; i >= 0 ; --i) {
for(int j = 0 ; j <= 3 ; ++j) dp[cur ^ 1][j] = 100000;
int x = (l >> i) & 1,y = (r >> i) & 1;
for(int s = 0 ; s <= 3 ; ++s) {
for(int k = 0 ; k <= 1 ; ++k) {
int t = 0;
if(s & 1) {
if(k < x) continue;
if(k == x) t |= 1;
}
if(s & 2) {
if(k > y) continue;
if(k == y) t |= 2;
}
dp[cur ^ 1][t] = min(dp[cur][s] + k,dp[cur ^ 1][t]);
}
}
cur ^= 1;
}
int res = 100000;
for(int i = 0 ; i <= 3 ; ++i) {
res = min(res,dp[cur][i]);
}
return res;
}
void Insert(int64 l,int64 r,int k) {
int64 rem = K - k - minpopcount(l,r);
if(rem < 0) return;
int64 t = 1;
while(k--) t *= 2;
++tot;
for(int i = 1 ; i <= N ; ++i) {
seq[tot].c[i] = a[i] / t;
if(a[i] % t < l) {
seq[tot].c[i] -= 1;
if(seq[tot].c[i] < 0) {--tot;return;}
}
rem = min(rem,seq[tot].c[i]);
}
seq[tot].u = rem;
for(int i = N ; i >= 2 ; --i) {
seq[tot].c[i] = seq[tot].c[i] - seq[tot].c[i - 1];
}
}
void Solve() {
read(N);read(K);
int64 mv = 0;
for(int i = 1 ; i <= N ; ++i) {read(a[i]);mv = max(mv,a[i]);}
int up = 0;
while(mv) {++up;mv >>= 1;}
int64 t = 1;
for(int i = 0 ; i <= up ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
rk[j] = a[j] % t;
}
sort(rk + 1,rk + N + 1);
rk[N + 1] = t - 1;
Insert(0,rk[1],i);
for(int j = 2 ; j <= N + 1 ; ++j) {
if(rk[j] != rk[j - 1]) Insert(rk[j - 1] + 1,rk[j],i);
}
t *= 2;
}
sort(seq + 1,seq + tot + 1);
range.pb(mp(seq[1].c[1] - seq[1].u,seq[1].c[1]));
int ans = 0;
for(int i = 2 ; i <= tot + 1; ++i) {
if(i == tot + 1 || seq[i] != seq[i - 1]) {
sort(range.begin(),range.end());
int64 st = range[0].fi,ed = range[0].se;
for(int k = 1 ; k < range.size() ; ++k) {
if(range[k].fi > ed) {
ans = inc(ans,(ed - st + 1) % MOD);
st = range[k].fi;ed = range[k].se;
}
else ed = max(range[k].se,ed);
}
ans = inc(ans,(ed - st + 1) % MOD);
range.clear();
}
range.pb(mp(seq[i].c[1] - seq[i].u,seq[i].c[1]));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
【AtCoder】ARC086的更多相关文章
- 【AtCoder】ARC086 E - Smuggling Marbles
[题目]E - Smuggling Marbles [题意]给定n+1个点的树(root=0),每个点可以选择放或不放弹珠,每一轮顺序进行以下操作: 1.将根节点0的弹珠加入答案. 2.每个点的弹珠移 ...
- 【AtCoder】ARC092 D - Two Sequences
[题目]AtCoder Regular Contest 092 D - Two Sequences [题意]给定n个数的数组A和数组B,求所有A[i]+B[j]的异或和(1<=i,j<=n ...
- 【Atcoder】CODE FESTIVAL 2017 qual A D - Four Coloring
[题意]给定h,w,d,要求构造矩阵h*w满足任意两个曼哈顿距离为d的点都不同色,染四色. [算法]结论+矩阵变换 [题解] 曼哈顿距离是一个立着的正方形,不方便处理.d=|xi-xj|+|yi-yj ...
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
[题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...
- 【AtCoder】ARC067 F - Yakiniku Restaurants 单调栈+矩阵差分
[题目]F - Yakiniku Restaurants [题意]给定n和m,有n个饭店和m张票,给出Ai表示从饭店i到i+1的距离,给出矩阵B(i,j)表示在第i家饭店使用票j的收益,求任选起点和终 ...
- 【AtCoder】ARC095 E - Symmetric Grid 模拟
[题目]E - Symmetric Grid [题意]给定n*m的小写字母矩阵,求是否能通过若干行互换和列互换使得矩阵中心对称.n,m<=12. [算法]模拟 [题解]首先行列操作独立,如果已确 ...
- 【Atcoder】AGC022 C - Remainder Game 搜索
[题目]C - Remainder Game [题意]给定n个数字的序列A,每次可以选择一个数字k并选择一些数字对k取模,花费2^k的代价.要求最终变成序列B,求最小代价或无解.n<=50,0& ...
随机推荐
- 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest C(记忆化搜索)
C题 Problem C Game Map 思路: 之前暴力搜索写了好几发,一直超时,后面看其他人的题解发现要用记忆化搜索..直接暴力搜的话有太多重 复的计算. dist u 表示以u 为起点所能走的 ...
- 【题解】 bzoj1923: [Sdoi2010]外星千足虫 (线性基/高斯消元)
bzoj1923,戳我戳我 Solution: 这个高斯消元/线性基很好看出来,主要是判断在第K 次统计结束后就可以确定唯一解的地方和\(bitset\)的骚操作 (我用的线性基)判断位置,我们可以每 ...
- 【BZOJ1293】[SCOI2009]生日礼物(单调队列)
[BZOJ1293][SCOI2009]生日礼物(单调队列) 题面 BZOJ 洛谷 题解 离散之后随便拿单调队列维护一下就好了. #include<iostream> #include&l ...
- 【bzoj4730】 Alice和Bob又在玩游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=4730 (题目链接) 题意 给出一个森林,两个人轮流操作,每次把一个节点以及它的祖先全部抹去,无节点可 ...
- 内置函数enumerate()
enumerate是枚举的意思,顾名思义,enumerate()函数用来将一个可迭代序列生成一个enumerate对象,该enumerate对象的每个元素是由可迭代对象的索引编号和对应的元素组成的元祖 ...
- 解题:UOJ #46 玄学
题面 二进制分组,修改把区间拆开丢在后面,合并的时候归并最后两块:查询在对应节点上二分答案 #include<cstdio> #include<cstring> #includ ...
- 【java】JDK、JRE、JVM的关系
目录结构: contents structure [-] 什么是JDK,JRE,JVM 安装JDK的时候为什么有两个jre 专用JRE 共用JRE 共用JRE和专用JRE的对比 java的跨平台特性 ...
- mybatis与分布式事务的面试
mybatis的面试: https://www.cnblogs.com/huajiezh/p/6415388.html 本地事务与分布式事务: https://www.cnblogs.com/xcj2 ...
- 关于System.getProperty("java.io.tmpdir");的输出,及System.getProperty();参数
1,首先来介绍下System.getProperty("java.io.tmpdir")输出因为这个输出有点特殊. 理论介绍:他是获取系统临时目录.可以是window的temp,l ...
- 洛谷 P1478 陶陶摘苹果(升级版)
本萌新第一次发布题解,若有不严谨处请谅解. 我看了前面几位大佬的手笔,表示自己还是比较钟爱桶排序的.它非常简易直接,还省时间,尤其对于这类题目占用的的空间也很小. 我们看到题目下面的说明:xi< ...