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