AGC034
そう長くのためのブラシAtCoder私は自分自身にまだのみABCE(マニュアル別れを見つけました
A - Kenken Race
行は、各点がホップ・ステップすることができますまたは二段ジャンプを、各グリッドは、オープンスペースや石である旨、各ステップに必要な石は、私たちが見つけることができるかどうか、または誰かのグリッド上で行くことができない\(\)は、に移動します\( C \)、\ (Bの\は)に移動される\(D \)、\ (A <C、B <D、A <B \)
参照(\)\する(C \)\と\(B \)をする(D \)を\全く正当が存在しない、2個の石をそこ方法
場合は\(\)が交差する必要があります\(B \)を、その後、参照\(B \)をする(D \)を\ない合法的な、そこに道3リンクされた空間には何のではありません
#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 ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
B - ABC
あなたが選択するたびに\(ABC \)がなることができます\(BCA \) 、ほとんどのいくつかの操作を尋ねました
統計\(私は\)接尾辞に続いては、多くを開始しました\(BC \を)
もし\(S [I] == B 、S [I + 1] == C \) 次に\(SUF [I] = SUF [I + 2] + 1 \)
もし\(S [I] == A \) 次に\(SUF [I] = SUF [I + 1] \)
それぞれの答えは\(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 ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
C - テスト
試験との二人は、最初の人は、各被験者のスコアに重要度を割り当てることができるという効果に、そして自分自身必死に学校、すべての学校支店(各被験者のための重要度間隔、この区間内で選択された最初の人です)この分割は一時間+1のスコアとなり、スコアがXの上限は、各被験者のために各被験者についての最終スコアを請求する最初の人は以上の各被験者の等しい重要性の重要性を取り、各被験者の乗車のために第二の個々のスコアは、少なくとも最初の人に尋ねますどのくらい学びます
各被験者の重要度が固定されている場合は、確かに重要な最初の人が、最初の二番目に大きいを学ぶために、最大限の外に学ぶことを検討し、答えは確かにX未満の部門まで追加、Xの数になります
回答の形で、我々はこの問題を振り返る、あなたは、k個のXのXを貪欲選んX番号の後に二人を導くために、各科学のために計算することができますが再選、秒を超えた最初の人になりますの1
その後、各被験者を列挙、プラス彼らの最大のk-Xに加えて、その後、単調関数を半分にすることができ二人よりも、この科学であることができますどのくらい列挙するので、彼は終了
#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 ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
D - マンハッタン最大マッチング
タイトルのNの意味は平面で赤い点及び一つの青色n個の点で、赤と青のドットの各々は、各2のマッチング値を必要な2つの2つの赤色のバスケットボールの試合の合計数に等しいいくつかの赤いボールやバスケットボールを有します点マンハッタン距離、10000を超えない、N <= 1000
低レベル、通常は必ずしもない費用流問題を参照してください
コストの優れた流動特性に、コストの流れを見つけることは容易である私たちは、4つのマンハッタン距離の中で最大の拡張の種類を選択するのに役立ち、私たちはドットの4種類を設定することができ、拡張の4種類を表し、辺の数がされていません\(N ^ 2 \)の代わりに\(N \) A
#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 ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}
E - 完全な圧縮
質問の意味:各点は、最初にマークを有していてもよく、次の2つのそれぞれが、少なくとも2の距離に、最初の時点を少なくとも一つのマーカーポイントを持ち、同時に近い離れステップからの場所に選択することができ、質問しませんポイントへのすべてのポイントがあり、最小距離を見つけます
列挙エンド\(uが\) 、全てのマークされた点とならば\(U \)距離とされている(X \)\、次いで場合\(X \)があれば明らかに奇数であることは、ステージに来る\(X \)でも、その後、答えがでなければなりません\(FRACは{X} {\ 2} \) 今、私たちはただそこにあるかどうかを答えることを宣告
提供存在する\(Uを\)サブツリー内の点のほとんどはすべての点の半分に等しい点未満であるという条件を満たす数を有する、異なるサブツリーに組み合わせることができ、各サブツリー内の点を除去した後
しかしながら、可能なサブツリーはまた、我々は、各点について計算ボトムアップDPはまで低減することができる持っているどのくらいの距離、距離の部分を低減、オフペアリングすることができます
#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 ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
F - RNGとXOR
タイトル効果:各数に対して一定の確率の生成と乱数発生器\(0 \)のために\(2 ^ {N} - 1 \) 整数値、初期Xは、ある数値を生成するために動作する各\ (V \)は、その後、\(Xは、= X \ oplus V \) そのシンボルはQから、XORである\(X- \)する初めて\ - ([0,2 ^ {N } 1] \) 所望しますステップの数はどのくらいです
我々は、より多数になることができる\(Iは\)に(0 \)\明らかに等価であるステップの所望の数、
\ [X_ {I} =( \ sum_ {J = 0} ^ {2 ^ {Nを} - {J} 1} P_ X_ {J \ I} Oplus)+ 1 \]
EM、このフォームは役に立たない表示します
だから我々は、過去の動きを入れて
\ [X_ {I} - 1
= \ sum_ {J = 0} ^ {2 ^ {N} - 1} \ P_ {J} X_ {iのj個の\ oplus}] だから私たちが考えることができます。。。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)\]
?\(\)何をする必要があります。。合計は前と同じとも見出され、次にであるべきである\(?\)である\(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、少しスキルがあり、\(P_0 \)はマイナス1、我々が得た変数の背中を見つけるのは簡単です!
\ [(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)\] この場合、我々はFWT排他的または同等のシークデコンボリューション、これは同様の再帰的を達成することができます
それは層である持って終了
\ [X_ {0} + X_1 \ bigoplus(P_ {0} - 1 + P_ {1} + P_ {2 - + X_2 + X_3 + \ cdots + X_ {1 2 ^ {N}} } + P_ {3} + \
cdots + P_ {2 ^ {N} - 1})= 0 \] 寄与しないこの時点で、私たちはそれぞれに選択\は(X \)であるプラス定数、そして最後に\(X_ {0} = 0 \) 、この層は任意の正の数に戻ることができ、この定数を排除します
#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);
}
const int MOD = 998244353,inv2 = (MOD + 1) / 2;
int N,A[(1 << 18) + 5],S;
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;
}
vector<int> trans(vector<int> p,vector<int> m) {
if(p.size() == 1) {
if(p[0] == 0 && m[0] == 0) return (vector<int>){1};
else return (vector<int>){mul(m[0],fpow(p[0],MOD - 2))};
}
vector<int> p0,p1,m0,m1;
for(int i = 0 ; i < p.size() ; i += 2) {
p0.pb(inc(p[i],p[i + 1]));
p1.pb(inc(p[i],MOD - p[i + 1]));
m0.pb(inc(m[i],m[i + 1]));
m1.pb(inc(m[i],MOD - m[i + 1]));
}
p0 = trans(p0,m0);p1 = trans(p1,m1);
vector<int> res;
for(int i = 0 ; i < p0.size() ; ++i) {
res.pb(mul(inc(p0[i],p1[i]),inv2));
res.pb(mul(inc(p0[i],MOD - p1[i]),inv2));
}
return res;
}
void Solve() {
read(N);
for(int i = 0 ; i < (1 << N) ; ++i) {
read(A[i]);
update(S,A[i]);
}
S = fpow(S,MOD - 2);
for(int i = 0 ; i < (1 << N) ; ++i) {
A[i] = mul(A[i],S);
}
vector<int> a,b;
b.pb((1 << N) - 1);
for(int i = 1 ; i < (1 << N) ; ++i) b.pb(-1);
for(int i = 0 ; i < (1 << N) ; ++i) {
int t = A[i];
if(i == 0) t = inc(t,MOD - 1);
a.pb(t);
}
vector<int> ans = trans(a,b);
for(int i = 0 ; i < (1 << N) ; ++i) {
out(inc(ans[i],MOD - ans[0]));enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}