從最後開始間隔着取就行node
#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 N; int a[MAXN * 3]; void Solve() { read(N); for(int i = 1 ; i <= 3 * N ; ++i) read(a[i]); sort(a + 1,a + 3 * N + 1); int64 ans = 0; for(int i = 3 * N - 1 ; i >= N + 1 ; i -= 2) { ans += a[i]; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:有一張圖,每一個操做是把從v開始距離不超過d的點染成c,求每一個點最後的顏色,d<=10c++
每一個點拆成10個,表示從第i個點出發能延伸j長度的詢問標號最大的顏色spa
從後往前處理顏色,遇到不能更新的中止便可code
複雜度\(O(dN + M)\)字符串
#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); } struct node { int to,next; }E[MAXN * 2]; int head[MAXN],sumE; int N,M,Q; int dp[MAXN][11]; int c[MAXN],d[MAXN],v[MAXN]; void add(int u,int v) { E[++sumE].to = v;E[sumE].next = head[u];head[u] = sumE; } void dfs(int v,int d) { if(!d) return; for(int i = head[v] ; i ; i = E[i].next) { int t = E[i].to; if(dp[t][d - 1] < dp[v][d]) { dp[t][d - 1] = dp[v][d]; dfs(t,d - 1); } } } void Solve() { read(N);read(M); int a,b; for(int i = 1 ; i <= M ; ++i) { read(a);read(b); add(a,b);add(b,a); } read(Q); for(int i = 1 ; i <= Q ; ++i) { read(v[i]);read(d[i]);read(c[i]); } for(int i = Q ; i >= 1 ; --i) { if(dp[v[i]][d[i]] < i) { dp[v[i]][d[i]] = i; dfs(v[i],d[i]); } } for(int i = 1 ; i <= N ; ++i) { int g = 0; for(int j = 0 ; j <= 10 ; ++j) { g = max(g,dp[i][j]); } out(c[g]);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:構造一個字符串s長度不超過200,字符集不超過100,要求s的子序列中知足能長度爲偶數,前一半字符串和後一半相同的個數正好爲Nget
有點神仙的一道題it
就是扔一個1,2,3,4,5,6...N在後面,前面構造一個序列使得最長上升序列爲給定值便可class
咱們發現構造一個最長上升序列時,把最大值扔在前面能夠+1,扔在最後能夠乘2test
那麼N只要80左右,總長度是160左右就能夠構出來了date
#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); } vector<int> p; int64 N; void Solve() { read(N); int num = 0,t; ++N; for(int i = 40 ; i >= 0 ; --i) { if((N >> i) & 1) { t = i; break; } } for(int i = t - 1 ; i >= 0 ; --i) { ++num; p.pb(num); if((N >> i) & 1) { ++num; p.insert(p.begin(),num); } } t = p.size(); for(int i = 1 ; i <= t ; ++i) p.pb(i); out(p.size());enter; for(auto a : p) { out(a);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:每次選兩個相同顏色的球價值總和不超過X,或兩個不一樣顏色的球價值不超過Y,能夠交換位置,求不一樣的顏色序列數
能夠把每一個點若是能連到同顏色最小點,就和同顏色最小點的並查集連起來
不然若是已是同顏色最小點或者和同顏色最小點沒法連,就和異顏色最小點連起來
只須要處理出價值最小且顏色不一樣的前兩個點便可
以後選出價值最小的那個點的集合(由於若顏色能夠交換則必定和它在一個集合)用可重全排列的式子算一下便可
#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); } const int MOD = 1000000007; int fac[MAXN],invfac[MAXN],N,X,Y; int vp[MAXN],fa[MAXN],id[MAXN]; pii c[MAXN]; 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; } int getfa(int x) { return fa[x] == x ? x : fa[x] = getfa(fa[x]); } void Solve() { read(N);read(X);read(Y); for(int i = 1 ; i <= N ; ++i) { read(c[i].se);read(c[i].fi); } sort(c + 1,c + N + 1); int sec = 2; while(sec <= N && c[sec].se == c[1].se) ++sec; if(sec > N) {puts("1");return;} for(int i = N ; i >= 1 ; --i) { vp[c[i].se] = i; fa[i] = i; } for(int i = N ; i >= 1 ; --i) { if(i != vp[c[i].se] && c[i].fi + c[vp[c[i].se]].fi <= X) { fa[getfa(i)] = getfa(vp[c[i].se]); } else if(c[i].se != c[1].se && c[i].fi + c[1].fi <= Y) { fa[getfa(i)] = getfa(1); } else if(c[i].se != c[sec].se && c[i].fi + c[sec].fi <= Y) { fa[getfa(i)] = getfa(sec); } } fac[0] = 1; for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i); invfac[N] = fpow(fac[N],MOD - 2); for(int i = N - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); int siz = 0; for(int i = 1 ; i <= N ; ++i) { if(getfa(i) == getfa(1)) { id[c[i].se]++; ++siz; } } int ans = fac[siz]; for(int i = 1 ; i <= N; ++i) { ans = mul(ans,invfac[id[i]]); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:有n個綠洲排成一排,駱駝能裝V的水,最多隻能走V的路,或者跳一步到任一點,可是容量變成\(\lfloor \frac{V}{2} \rfloor\),已經儲存的水變爲0,到了一個綠洲能夠吸水,一個綠洲能夠吸任意屢次的水,問從某個綠洲出發可否遍歷全部綠洲
咱們顯然有\(log V\)種不一樣的容量,也就是當咱們選擇了一塊區間(這個區間裏的點兩兩距離不超過V,且至多隻有logV個區間不然必定impossible)
對於每次容量時,我能夠選擇這個容量在區間左邊用仍是右邊用,分別是前綴和後綴
因而咱們對於前綴dp一個dp[S]表示用了S這個集合的容量,最遠能夠走遍的前綴是dp[S],後綴同理
因而只須要求出來一個S,\(dpL[S] >= l - 1\)而且\(dpR[All \otimes S] <= r + 1\)便可認爲這個區間裏的點能夠遍歷全部綠洲了
#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,V; int x[MAXN],d[30],tot,r[30][MAXN],l[30][MAXN]; int dp[2][(1 << 19) + 5]; void Solve() { read(N);read(V); for(int i = 1 ; i <= N ; ++i) read(x[i]); d[0] = V / 2; while(d[tot]) { ++tot; d[tot] = d[tot - 1] / 2; } for(int j = 0 ; j <= tot ; ++j) { r[j][N] = N;r[j][N + 1] = N + 1; for(int i = N - 1 ; i >= 1 ; --i) { r[j][i] = i; if(x[i + 1] - x[i] <= d[j]) r[j][i] = r[j][i + 1]; } l[j][1] = 1; for(int i = 2 ; i <= N ; ++i) { l[j][i] = i; if(x[i] - x[i - 1] <= d[j]) l[j][i] = l[j][i - 1]; } } dp[0][0] = 0;dp[1][0] = N + 1; for(int S = 1 ; S < (1 << (tot + 1)) ; ++S) { dp[1][S] = N + 1; for(int j = 0 ; j <= tot ; ++j) { if(S >> j & 1) { dp[0][S] = max(r[j][dp[0][S ^ (1 << j)] + 1],dp[0][S]); dp[1][S] = min(l[j][dp[1][S ^ (1 << j)] - 1],dp[1][S]); } } } int cnt = 0; for(int i = 1 ; i <= N ; ++i) { int l = i,r = i; while(r < N && x[r + 1] - x[r] <= V) ++r; i = r; ++cnt; } if(cnt - 1 > tot + 1) { for(int i = 1 ; i <= N ; ++i) { puts("Impossible"); } return; } for(int i = 1 ; i <= N ; ++i) { int l = i,r = i; while(r < N && x[r + 1] - x[r] <= V) ++r; int A = (1 << tot + 1) - 1; bool f = 0; for(int S = 0 ; S < (1 << tot + 1) ; ++S) { if(dp[0][S] >= l - 1 && dp[1][A ^ S] <= r + 1) {f = 1;break;} } for(int i = l ; i <= r ; ++i) { if(f) puts("Possible"); else puts("Impossible"); } i = r; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:2×N- 1個數,能夠重排,每次拿前2×i - 1的中位數做爲\(b_{i}\),求不一樣的\(b_{i}\)的個數
從後往前數,最後一個確定是全局中位數
事實上咱們的選擇須要知足第一個數在中間1個,第二個數在中間3箇中,第三個數在中間5箇中,數能夠重複選擇
還有要知足的就是不存在\((i < j) B_{j} < B_{i} < B_{j + 1}\)或者\((i < j) B_j > B_{i} > B_{j + 1}\)
這是必要的,能夠證實這是充分的
也就是咱們對於\(B_{1},B_{2}...B_{n}\)知足這些條件,就必定能夠被構造出來
從後往前構造
\(B_{N}\)固定了
咱們要選擇\(B_{i}\)的時候,若是\(B_{i}\)和\(B_{i + 1}\)同樣,咱們就刪掉左邊未出現的數最大的,和右邊未出現的數最小的
若是\(B_{i} < B_{i + 1}\)那麼咱們刪掉\(B_1....B_{i - 1}\)中在右邊未出現的最小的兩個
最後一種狀況同理
這樣的話也就是已經存在的值域中選左右的兩部分,不能選值域非端點的中間
dp狀態是\(dp[i][j][k]\)表示從後往前填到第i個數,值域有j個數,當前數是第k個
#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); } const int MOD = 1000000007; int N; int dp[55][105][105]; int a[105],id[MAXN],tot; 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); } void Solve() { read(N); for(int i = 1 ; i <= 2 * N - 1 ; ++i) read(a[i]); sort(a + 1,a + 2 * N); dp[1][1][1] = 1; for(int i = 1 ; i < N ; ++i) { for(int j = 1 ; j <= 2 * N - 1 ; ++j) { for(int h = 1 ; h <= j ; ++h) { int tj = j,th = h; if(a[N + i] != a[N + i - 1]) ++tj; if(a[N - i] != a[N - i + 1]) ++tj,++th; for(int k = 1 ; k <= tj ; ++k) { if(k < th) update(dp[i + 1][k + tj - th + 1][k],dp[i][j][h]); else if(k > th) update(dp[i + 1][th + tj - k + 1][th + 1],dp[i][j][h]); else if(k == th) update(dp[i + 1][tj][th],dp[i][j][h]); } } } } int ans = 0; for(int j = 1 ; j <= 2 * N - 1 ; ++j) { for(int h = 1 ; h <= j ; ++h) { update(ans,dp[N][j][h]); } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }