若是i + j走过的格子只有一个,那么就是能够走到c++
#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 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 H,W,cnt[30]; char s[15][15]; bool vis[15][15]; void Solve() { read(H);read(W); for(int i = 1 ; i <= H ; ++i) { scanf("%s",s[i] + 1); } for(int i = 1 ; i <= H ; ++i) { for(int j = 1 ; j <= W ; ++j) { if(s[i][j] == '#') { ++cnt[i + j]; if(cnt[i + j] >= 2) {puts("Impossible");return;} } } } puts("Possible"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
把a标成\(i*N\)spa
把b标成\((N - i + 1) * N\)code
此时a和b按位相加后相等,而后按照排列的顺序,给第一个排列所在的b加0,第二个+1,第三个+2...就能够了队列
#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 205 //#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; int a[20005],b[20005],p[20005]; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) read(p[i]); for(int i = 1 ; i <= N ; ++i) {b[i] = (N - i + 1) * N; a[i] = i * N;} for(int i = 1 ; i <= N ; ++i) { b[p[i]] += i - 1; } for(int i = 1 ; i <= N ; ++i) { out(a[i]);space; } enter; for(int i = 1 ; i <= N ; ++i) { out(b[i]);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
这个须要注意到,当咱们一个球进洞后,其他的球仍是原来的形态,且差距\(d_{i}\)仍然是一个等差数列字符串
咱们每次的指望就是\(\frac{2nd + 2n(2n - 1)x/2}{2n} = d + (2n - 1)x / 2\)get
推一下式子发现新的首项是string
\(d' = (n + 1)d/ n + 5x /2n\)it
\(x' = (n + 2)x / n\)class
而后\(n - 1\),继续计算gc
#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 205 //#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; db d,x; void Solve() { read(N); scanf("%lf%lf",&d,&x); db ans = 0; while(N) { ans += d + (2 * N - 1) / 2.00 * x; d = 1.0 * (N + 1) / N * d + 5 * x / (2 * N); x = 1.0 * (N + 2) / N * x; --N; } printf("%.10lf\n",ans); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
至关于除掉我必须从0走到1的点,我在上面须要绕几个环
很显然,环是互相分离的,由于若是环的最靠前一个点有钱,走回去的路上钱都会被捡起来
这样就很容易dp了,咱们能够把E去掉,求附加的最小时间
设\(dp[i]\)表示走到i且i的钱被捡完了的最小附加时间
若是从前面一个\(j\)转移过来,若\(2(x[i] - x[j]) >= T\),那么这一圈的附加时间应该是\(2(x[i] - x[j])\),不然应该是T
这两个分别能够用前缀最小值和单调队列维护,复杂度\(O(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 205 //#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); } int64 dp[100005],pre; int64 T,E; int64 x[100005]; int N,p; deque<int> que; void Solve() { read(N);read(E);read(T); for(int i = 1 ; i <= N ; ++i) {read(x[i]);dp[i] = i * T;} p = -1;pre = 1e18; que.push_back(0); for(int i = 1 ; i <= N ; ++i) { while(p < i - 1 && 2 * (x[i] - x[p + 2]) > T) { ++p;pre = min(pre,dp[p] - 2 * x[p + 1]); } dp[i] = min(dp[i],pre + 2 * x[i]); while(!que.empty() && 2 * (x[i] - x[que.front() + 1]) > T ) {que.pop_front();} if(!que.empty()) { dp[i] = min(dp[i],dp[que[0]] + T); } while(!que.empty() && dp[que.back()] > dp[i]) que.pop_back(); que.push_back(i); } out(dp[N] + E);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
咱们记录一个点对为这棵子树中往上延伸的两条链长度\((a,b)\)咱们合并的时候用两个子树里的\((a,b)\)和\((c,d)\)合并,二分答案来限制合并的链长不超过某个值
合并的时候用含点对少的和含点对多的合并,新合出来的不会超过点对少的的两倍,少的中每个点对\((a,b)\)能够找到\((a,u)\),u是另外一棵树能合出来最小的,b同理
这样就能够作了
#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 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; int64 val[MAXN],lim,pre[MAXN]; vector<int> son[MAXN]; vector<pair<int64,int64> > v[MAXN]; vector<pair<int64,int64> > tmp,ano; bool flag = 0; void dfs(int u) { if(flag) return; v[u].clear(); if(son[u].size() == 0) {v[u].pb(mp(0,0));return;} dfs(son[u][0]);dfs(son[u][1]); int a = son[u][0],b = son[u][1]; if(v[a].size() > v[b].size()) swap(a,b); tmp.clear();ano.clear(); for(auto t : v[a]) { tmp.pb(mp(t.fi,t.se));tmp.pb(mp(t.se,t.fi)); } sort(tmp.begin(),tmp.end()); for(auto t : v[b]) { ano.pb(mp(t.fi,t.se));ano.pb(mp(t.se,t.fi)); } sort(ano.begin(),ano.end()); int r = ano.size() - 1; pre[0] = ano[0].se; for(int i = 1 ; i < ano.size() ; ++i) pre[i] = min(pre[i - 1],ano[i].se); for(auto t : tmp) { while(r >= 0 && ano[r].fi + val[b] + t.fi + val[a] > lim) --r; if(r >= 0) { v[u].pb(mp(pre[r] + val[b],t.se + val[a])); } } if(!v[u].size()) flag = 1; return; } bool check(int64 mid) { lim = mid; flag = 0;dfs(1); if(flag) return false; return true; } void Solve() { read(N); int a; for(int i = 1 ; i < N ; ++i) { read(a); son[a].pb(i + 1);read(val[i + 1]); } int64 L = 0,R = 1e16; while(L < R) { int64 mid = (L + R) >> 1; if(check(mid)) { R = mid; } else L = mid + 1; } out(L);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
咱们先对每一个点找一个匹配点,这个点就是\(t[i] == s[j]\)且j最小的位置
且对于i的匹配点必须是递增的
而后咱们至关于从每一个匹配点在一个高度无限,宽度为字符串长度,开始每步第一次能够往下走,而后往右走,直到走到匹配的最后一个位置
咱们要求的就是这列路径的最大高度
从后往前开始递推,遇到一个结束位置,高度加1,并且全部的降低位置须要+1
若是这一列位置是个降低位置,上面还有c条线,我能够拖到i - c的位置再降低(咕咕咕是人类的本质)
#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 1000005 //#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; char s[MAXN],t[MAXN]; int pos[MAXN],suf[MAXN],to[MAXN],turn[MAXN]; void Solve() { read(N); scanf("%s",s + 1); scanf("%s",t + 1); bool f = 1; for(int i = 1 ; i <= N ; ++i) { if(s[i] != t[i]) {f = 0;break;} } if(f) {puts("0");return;} int p = N; for(int i = N ; i >= 1 ; --i) { p = min(p,i); while(p >= 1 && s[p] != t[i]) --p; if(p == 0) {puts("-1");return;} if(!pos[p]) pos[p] = i; to[i] = p; } int cnt = 0,t = 0; int ans = 0; for(int i = N ; i >= 1 ; --i) { suf[i] = suf[i + 1]; if(pos[to[i]] == i) { ++suf[i];++cnt;++t; } ans = max(suf[i],ans); if(pos[i]) { --cnt; turn[i - cnt + t]++; } suf[i] -= turn[i + t];turn[i + t] = 0; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }