若是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; }