【AtCoder】AGC034
AGC034
刷了那么久AtCoder我發(fā)現(xiàn)自己還是只會(huì)ABCE(手動(dòng)再見(jiàn)
A - Kenken Race
大意是一個(gè)橫列,每個(gè)點(diǎn)可以跳一步或者跳兩步,每個(gè)格子是空地或者石頭,要求每一步不能走到石頭或者有人的格子上,求是否能把\(A\)移動(dòng)到\(C\),\(B\)移動(dòng)到\(D\),\(A < C,B < D,A < B\)
看\(A\)到\(C\)和\(B\)到\(D\)的路上有沒(méi)有兩個(gè)連在一起的石頭,有就不合法
如果\(A\)需要越過(guò)\(B\),則看\(B\)到\(D\)的路上有沒(méi)有三個(gè)連在一起的空格,沒(méi)有就不合法
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 200005 #define ba 47 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) {res = 0;T f = 1;char c = getchar();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,A,B,C,D; char s[MAXN]; void Solve() {read(N);read(A);read(B);read(C);read(D);scanf("%s",s + 1);int ed = max(C,D),st = min(A,B);for(int i = st + 1 ; i <= ed ; ++i) {if(s[i] == '#' && s[i - 1] == '#') {puts("No");return;}}if(C > D) {bool f = 0;for(int i = B ; i <= D ; ++i) {if(s[i] == '.' && s[i - 1] == '.' && s[i + 1] == '.') {f = 1;break;}}if(!f) {puts("No");return;}}puts("Yes"); } int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifSolve(); }B - ABC
每次選擇\(ABC\)可以變成\(BCA\),問(wèn)最多幾次操作
統(tǒng)計(jì)以\(i\)為開(kāi)始的后綴緊跟著有多少\(BC\)
如果\(s[i] == B,s[i + 1] == C\)那么\(suf[i] = suf[i + 2] + 1\)
如果\(s[i] == A\)那么\(suf[i] = suf[i + 1]\)
答案是每個(gè)\(s[i] == A\)的\(suf[i]\)
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 200005 #define ba 47 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) {res = 0;T f = 1;char c = getchar();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); } char s[MAXN]; int L,suf[MAXN]; void Solve() {scanf("%s",s + 1);L = strlen(s + 1);int64 ans = 0;for(int i = L - 1; i >= 1 ; --i) {if(s[i] == 'B' && s[i + 1] == 'C') suf[i] = suf[i + 2] + 1;else if(s[i] == 'A') {suf[i] = suf[i + 1];ans += suf[i];}}out(ans);enter; } int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifSolve(); }C - Tests
大意是兩個(gè)人一起考試,第一個(gè)人可以給每科分?jǐn)?shù)分配一個(gè)重要度(每科的重要度是一個(gè)區(qū)間,第一個(gè)人在這個(gè)區(qū)間里選),然后自己拼命學(xué),每學(xué)一科一小時(shí)這科分?jǐn)?shù)就會(huì)+1,分?jǐn)?shù)有上限是X,要求最后第一個(gè)人每科分?jǐn)?shù)乘每科重要度大于等于第二個(gè)人每科分?jǐn)?shù)乘每科重要度,求第一個(gè)人至少要學(xué)多久
考慮一下,如果每科重要度固定了,第一個(gè)人肯定先把重要度最大的學(xué)到滿分,再學(xué)次大的,答案肯定會(huì)是若干個(gè)X,加上至多一科不到X的
有了答案的形式,我們回過(guò)頭來(lái)看這個(gè)問(wèn)題,可以對(duì)于計(jì)算每一科學(xué)到X后領(lǐng)先了第二個(gè)人多少,貪心的選k個(gè)X使得再選一個(gè)X,第一個(gè)人就超過(guò)第二個(gè)了
然后枚舉每一科,加上除了自己之外最大的k個(gè)X,再枚舉這一科學(xué)多久能超過(guò)第二個(gè)人,是個(gè)單調(diào)的函數(shù),可以二分,于是就做完了
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 #define ba 47 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) {res = 0;T f = 1;char c = getchar();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,pos,id[MAXN]; int64 l[MAXN],u[MAXN],b[MAXN],val[MAXN],X,all; bool vis[MAXN]; void Solve() {read(N);read(X);for(int i = 1 ; i <= N ; ++i) {read(b[i]);read(l[i]);read(u[i]);all -= b[i] * l[i];val[i] = (X - b[i]) * u[i] + b[i] * l[i];}for(int i = 1 ; i <= N ; ++i) id[i] = i;sort(id + 1,id + N + 1,[](int a,int b){return val[a] > val[b];});int64 sum = 0;for(int i = 1 ; i <= N ; ++i) {sum += val[id[i]];if(sum + all >= 0) {pos = i - 1;sum -= val[id[i]];break;}vis[id[i]] = 1;}all += sum;int64 ans = (pos + 1) * X; for(int i = 1 ; i <= N ; ++i) {int64 tmp = all;if(vis[i]) {tmp -= val[i];tmp += val[id[pos + 1]];}int64 L = 0,R = X + 1;while(L < R) {int64 mid = (L + R) >> 1;int64 sc = 0;if(mid >= b[i]) sc = (mid - b[i]) * u[i];else sc = (mid - b[i]) * l[i];if(tmp + b[i] * l[i] + sc >= 0) R = mid;else L = mid + 1;}if(R <= X) {ans = min(ans,pos * X + R);}}out(ans);enter;} int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifSolve(); }D - Manhattan Max Matching
題意是平面上有n個(gè)紅點(diǎn)和n個(gè)藍(lán)點(diǎn),每個(gè)紅點(diǎn)和藍(lán)點(diǎn)有若干個(gè)紅球或藍(lán)球,總數(shù)相等,要求紅藍(lán)球兩兩匹配,每個(gè)匹配的價(jià)值是兩點(diǎn)曼哈頓距離,總數(shù)不超過(guò)10000,n<=1000
水平低,看見(jiàn)費(fèi)用流的題總是做不出來(lái)
由于費(fèi)用流的優(yōu)秀性質(zhì),很容易發(fā)現(xiàn)費(fèi)用流可以幫助我們?cè)谒姆N曼哈頓距離展開(kāi)式中選擇最大的那種,于是我們建立四種點(diǎn)表示四種展開(kāi)式,邊數(shù)就不是\(N^2\)而是\(N\)了
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 2005 #define ba 47 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) {res = 0;T f = 1;char c = getchar();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 S,T,Ncnt,N; int a[2][MAXN],ty[4]; struct node {int to,next,cap;int64 val; }E[MAXN * 100]; int head[MAXN * 2],sumE = 1; int rx[MAXN],ry[MAXN],rc[MAXN]; int bx[MAXN],by[MAXN],bc[MAXN]; int dx[4] = {1,1,-1,-1}; int dy[4] = {1,-1,1,-1};void add(int u,int v,int c,int64 a) {E[++sumE].to = v;E[sumE].next = head[u];E[sumE].cap = c;E[sumE].val = a;head[u] = sumE; } void addtwo(int u,int v,int c,int64 a) {add(u,v,c,a);add(v,u,0,-a); } int64 dis[MAXN];bool inq[MAXN]; int preE[MAXN]; queue<int> Q; int64 SPFA() {for(int i = 1 ; i <= Ncnt ; ++i) dis[i] = -1e18;memset(inq,0,sizeof(inq));dis[S] = 0;inq[S] = 1;Q.push(S);while(!Q.empty()) {int u = Q.front();Q.pop();inq[u] = 0;for(int i = head[u] ; i ; i = E[i].next) {int v = E[i].to;if(E[i].cap) {if(dis[v] < dis[u] + E[i].val) {dis[v] = dis[u] + E[i].val;preE[v] = i;if(!inq[v]) {Q.push(v);inq[v] = 1;}}}}}return dis[T]; } void Init() {read(N);S = ++Ncnt;for(int i = 0 ; i < 2 ; ++i) {for(int j = 1 ; j <= N ; ++j) {a[i][j] = ++Ncnt;}}for(int i = 0 ; i < 4 ; ++i) ty[i] = ++Ncnt;T = ++Ncnt;for(int i = 1 ; i <= N ; ++i) {read(rx[i]);read(ry[i]);read(rc[i]);}for(int i = 1 ; i <= N ; ++i) {read(bx[i]);read(by[i]);read(bc[i]);}for(int i = 1 ; i <= N ; ++i) {addtwo(S,a[0][i],rc[i],0);for(int j = 0 ; j < 4 ; ++j) {addtwo(a[0][i],ty[j],1e9,dx[j] * rx[i] + dy[j] * ry[i]);}}for(int i = 1 ; i <= N ; ++i) {addtwo(a[1][i],T,bc[i],0);for(int j = 0 ; j < 4 ; ++j) {addtwo(ty[j],a[1][i],1e9,-dx[j] * bx[i] - dy[j] * by[i]);}} } void Solve() {int64 ans = 0;while(SPFA() > 0) {int p = preE[T],f = 1e9;while(p) {f = min(f,E[p].cap);p = preE[E[p ^ 1].to];}ans += dis[T] * f;p = preE[T];while(p) {E[p].cap -= f;E[p ^ 1].cap += f;p = preE[E[p ^ 1].to];}}out(ans);enter; } int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifInit();Solve(); }E - Complete Compress
題意:每個(gè)點(diǎn)初始時(shí)可能有一個(gè)標(biāo)記,每次可以選擇兩個(gè)至少有一個(gè)標(biāo)記的點(diǎn),初始的時(shí)候點(diǎn)要距離至少為2,然后同時(shí)往離的更近的地方走一步,問(wèn)可不可能把所有點(diǎn)移到一個(gè)點(diǎn)上,并且求最小距離
枚舉終點(diǎn)\(u\),如果所有帶標(biāo)記的點(diǎn)和\(u\)的距離的和是\(x\),那么如果\(x\)是奇數(shù)顯然走不到,如果\(x\)是偶數(shù),那么答案一定是\(\frac{x}{2}\)現(xiàn)在我們只要判答案是否存在
存在的前提是\(u\)去掉后每個(gè)子樹(shù)中的點(diǎn)可以和不同子樹(shù)中的配對(duì),滿足條件是含有點(diǎn)最多的子樹(shù)中的點(diǎn)的個(gè)數(shù)小于等于所有點(diǎn)的一半
但是可能子樹(shù)里也可以兩兩配對(duì),減小一部分距離,我們就自底向上dp計(jì)算每個(gè)點(diǎn)最多可以減少多少的距離
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 500005 #define ba 47 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) {res = 0;T f = 1;char c = getchar();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 MAXV = 150000,LEN = 450000; int N,M; int a[MAXN],d; int cnt[LEN + 5]; int getpos(int x) {return x - d + MAXV; } struct node {int l,r,val,cnt,lz; }tr[LEN * 4 + 5]; void update(int u) {tr[u].val = min(tr[u << 1].val,tr[u << 1 | 1].val);tr[u].cnt = 0;if(tr[u].val == tr[u << 1].val) tr[u].cnt += tr[u << 1].cnt;if(tr[u].val == tr[u << 1 | 1].val) tr[u].cnt += tr[u << 1 | 1].cnt; } void build(int u,int l,int r) {tr[u].l = l;tr[u].r = r;if(l == r) {tr[u].cnt = 1;return;}int mid = (l + r) >> 1;build(u << 1,l,mid);build(u << 1 | 1,mid + 1,r);update(u); } void addlz(int u,int v) {tr[u].val += v;tr[u].lz += v; } void pushdown(int u) {if(tr[u].lz) {addlz(u << 1,tr[u].lz);addlz(u << 1 | 1,tr[u].lz);tr[u].lz = 0;} } void add(int u,int l,int r,int v) {if(tr[u].l == l && tr[u].r == r) {addlz(u,v);return;}pushdown(u);int mid = (tr[u].l + tr[u].r) >> 1;if(r <= mid) add(u << 1,l,r,v);else if(l > mid) add(u << 1 | 1,l,r,v);else {add(u << 1,l,mid,v);add(u << 1 | 1,mid + 1,r,v);}update(u); } pii Query(int u,int l,int r) {if(tr[u].l == l && tr[u].r == r) return mp(tr[u].val,tr[u].cnt);pushdown(u);int mid = (tr[u].l + tr[u].r) >> 1;if(r <= mid) return Query(u << 1,l,r);else if(l > mid) return Query(u << 1 | 1,l,r);else {pii a = Query(u << 1,l,mid),b = Query(u << 1 | 1,mid + 1,r);if(a.fi > b.fi) swap(a,b);if(a.fi == b.fi) a.se += b.se;return a;} } void Solve() {read(N);read(M);build(1,1,LEN);for(int i = 1 ; i <= N ; ++i) {read(a[i]);a[i] += MAXV;add(1,a[i] - cnt[a[i]],a[i] - cnt[a[i]],1);cnt[a[i]]++;}int p,x;for(int i = 1 ; i <= M ; ++i) {read(p);read(x);if(p == 0) {if(x == 1) {if(cnt[getpos(N)]) {add(1,getpos(N) - cnt[getpos(N)] + 1,getpos(N),-1);}}else {if(cnt[getpos(N + 1)]) {add(1,getpos(N + 1) - cnt[getpos(N + 1)] + 1,getpos(N + 1),1);}}d += x;}else {if(a[p] <= getpos(N)) {add(1,a[p] - cnt[a[p]] + 1,a[p] - cnt[a[p]] + 1,-1);}cnt[a[p]]--;a[p] = x - d + MAXV;if(a[p] <= getpos(N)) {add(1,a[p] - cnt[a[p]],a[p] - cnt[a[p]],1);}cnt[a[p]]++;}pii res = Query(1,getpos(1),getpos(N));int ans = 0;if(res.fi == 0) ans = res.se;out(ans);enter;} } int main() { #ifdef ivorysifreopen("f1.in","r",stdin); #endifSolve(); }F - RNG and XOR
題目大意:有一個(gè)隨機(jī)數(shù)生成器每個(gè)數(shù)以一定概率生成\(0\)到\(2^{N} - 1\)的整數(shù)值,初始有一個(gè)X,每次進(jìn)行操作生成一個(gè)數(shù)\(v\),然后\(X = X \oplus v\)那個(gè)符號(hào)是異或,問(wèn)從\(X\)第一次到\([0,2^{N} - 1]\)的期望步數(shù)是多少
我們可以變成從一個(gè)數(shù)\(i\)到\(0\)的期望步數(shù),這顯然是等價(jià)的
\[ x_{i} = (\sum_{j = 0}^{2^{N} - 1} p_{j}x_{j \oplus i}) + 1 \]
em,這個(gè)形式看起來(lái)沒(méi)什么幫助
于是我們把1移過(guò)去
\[ x_{i} - 1 = \sum_{j = 0}^{2^{N} - 1} p_{j}x_{j \oplus i} \]
于是我們可以想到。。。FWT的異或卷積
\[ (x_{0},x_1,x_2,x_3\cdots x_{2^{N} - 1})\bigoplus(p_{0},p_{1},p_{2},p_{3}\cdots p_{2^{N} - 1}) = (?,x_{1} - 1,x_{2} - 1,x_{3} - 1,\cdots x_{2^{N} - 1} - 1) \]
\(?\)應(yīng)該是啥。。就是又發(fā)現(xiàn)前后的總和應(yīng)該不變,于是\(?\)就是\(x_{0} + 2^{N} - 1\)
于是式子變成
\[ (x_{0},x_1,x_2,x_3\cdots x_{2^{N} - 1})\bigoplus(p_{0},p_{1},p_{2},p_{3}\cdots p_{2^{N} - 1}) = (x_{0} + 2^{N}-1,x_{1} - 1,x_{2} - 1,x_{3} - 1,\cdots x_{2^{N} - 1} - 1) \]
em,又有個(gè)小技巧,把\(p_0\)減去1,很容易發(fā)現(xiàn)我們把后面的變量都消掉了!
\[ (x_{0},x_1,x_2,x_3\cdots x_{2^{N} - 1})\bigoplus(p_{0} - 1,p_{1},p_{2},p_{3}\cdots p_{2^{N} - 1}) = (2^{N}-1,- 1,- 1,- 1,\cdots - 1) \]
這樣的話,我們相當(dāng)于求一個(gè)FWT異或卷積的逆,這個(gè)可以類(lèi)似的遞歸實(shí)現(xiàn)
但是最后呢有一層是
\[ x_{0} + x_1 + x_2 + x_3 + \cdots + x_{2^{N} - 1}\bigoplus(p_{0} - 1 + p_{1} + p_{2} + p_{3} + \cdots + p_{2^{N} - 1}) = 0 \]
這個(gè)時(shí)候沒(méi)有什么貢獻(xiàn),于是我們選擇把每個(gè)\(x\)都加上一個(gè)常數(shù),最后用\(x_{0} = 0\)把這個(gè)常數(shù)消掉,于是到了這一層可以返回一個(gè)任意的正數(shù)
轉(zhuǎn)載于:https://www.cnblogs.com/ivorysi/p/10984113.html
總結(jié)
以上是生活随笔為你收集整理的【AtCoder】AGC034的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Pytest介绍
- 下一篇: AGC034 F - RNG and X