刷了那么久AtCoder我发现本身仍是只会ABCE(手动再见node
大意是一个横列,每一个点能够跳一步或者跳两步,每一个格子是空地或者石头,要求每一步不能走到石头或者有人的格子上,求是否能把\(A\)移动到\(C\),\(B\)移动到\(D\),\(A < C,B < D,A < B\)c++
看\(A\)到\(C\)和\(B\)到\(D\)的路上有没有两个连在一块儿的石头,有就不合法函数
若是\(A\)须要越过\(B\),则看\(B\)到\(D\)的路上有没有三个连在一块儿的空格,没有就不合法ui
#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(); }
每次选择\(ABC\)能够变成\(BCA\),问最多几回操做spa
统计以\(i\)为开始的后缀紧跟着有多少\(BC\)code
若是\(s[i] == B,s[i + 1] == C\)那么\(suf[i] = suf[i + 2] + 1\)递归
若是\(s[i] == A\)那么\(suf[i] = suf[i + 1]\)get
答案是每一个\(s[i] == A\)的\(suf[i]\)it
#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(); }
大意是两我的一块儿考试,第一我的能够给每科分数分配一个重要度(每科的重要度是一个区间,第一我的在这个区间里选),而后本身拼命学,每学一科一小时这科分数就会+1,分数有上限是X,要求最后第一我的每科分数乘每科重要度大于等于第二我的每科分数乘每科重要度,求第一我的至少要学多久class
考虑一下,若是每科重要度固定了,第一我的确定先把重要度最大的学到满分,再学次大的,答案确定会是若干个X,加上至多一科不到X的
有了答案的形式,咱们回过头来看这个问题,能够对于计算每一科学到X后领先了第二我的多少,贪心的选k个X使得再选一个X,第一我的就超过第二个了
而后枚举每一科,加上除了本身以外最大的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(); }
题意是平面上有n个红点和n个蓝点,每一个红点和蓝点有若干个红球或蓝球,总数相等,要求红蓝球两两匹配,每一个匹配的价值是两点曼哈顿距离,总数不超过10000,n<=1000
水平低,看见费用流的题老是作不出来
因为费用流的优秀性质,很容易发现费用流能够帮助咱们在四种曼哈顿距离展开式中选择最大的那种,因而咱们创建四种点表示四种展开式,边数就不是\(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 ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); }
题意:每一个点初始时可能有一个标记,每次能够选择两个至少有一个标记的点,初始的时候点要距离至少为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(); }
题目大意:有一个随机数生成器每一个数以必定几率生成\(0\)到\(2^{N} - 1\)的整数值,初始有一个X,每次进行操做生成一个数\(v\),而后\(X = X \oplus v\)那个符号是异或,问从\(X\)第一次到\([0,2^{N} - 1]\)的指望步数是多少
咱们能够变成从一个数\(i\)到\(0\)的指望步数,这显然是等价的
\[ x_{i} = (\sum_{j = 0}^{2^{N} - 1} p_{j}x_{j \oplus i}) + 1 \]
em,这个形式看起来没什么帮助
因而咱们把1移过去
\[ 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) \]
\(?\)应该是啥。。就是又发现先后的总和应该不变,因而\(?\)就是\(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 + 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 \]
这个时候没有什么贡献,因而咱们选择把每一个\(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(); }