大意:有N我的,每一個人只能在\([T_i,T_i +K]\)這段區間乘車,每輛車安排C人,問最少安排幾輛車node
直接掃,遇到一個沒有車的在\(T_i +K\)分配一輛ios
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <set> #include <cmath> #include <bitset> #include <queue> #define enter putchar('\n') #define space putchar(' ') //#define ivorysi #define pb push_back #define mo 974711 #define pii pair<int,int> #define mp make_pair #define fi first #define se second #define MAXN 500005 #define eps 1e-12 using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 - '0' + c; c = getchar(); } res = 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,C,K; int T[1000005]; void Solve() { read(N);read(C);read(K); for(int i = 1 ; i <= N ; ++i) read(T[i]); sort(T + 1,T + N + 1); int ans = 0; int cnt = 0,t = 0; for(int i = 1 ; i <= N ; ++i) { if(t < T[i] || !cnt) { ++ans; t = T[i] + K; cnt = C; } --cnt; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意:N個怪獸顏色兩兩不一樣,兩個怪物若是一個大小是A顏色是B,一個大小是C(C <= 2 * A)顏色是D,新怪物能夠是大小A+C,顏色是B,問最後多是幾種顏色c++
直接二分找知足要求的數的位置,而後能擴到的最大致積就是從最小的數到這個數的前綴和,每次至少擴大兩倍,因此只用log次優化
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <set> #include <cmath> #include <bitset> #include <queue> #define enter putchar('\n') #define space putchar(' ') //#define ivorysi #define pb push_back #define mo 974711 #define pii pair<int,int> #define mp make_pair #define fi first #define se second #define MAXN 500005 #define eps 1e-12 using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 - '0' + c; c = getchar(); } res = 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 A[100005],tmp[100005],sum[1000005]; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(A[i]); tmp[i] = A[i]; } tmp[N + 1] = 1000000001; sort(tmp + 1,tmp + N + 2); int ans = 0; for(int i = 1 ; i <= N ; ++i) { sum[i] = sum[i - 1] + tmp[i]; } for(int i = 1 ; i <= N ; ++i) { if(2 * A[i] >= tmp[N]) {++ans;continue;} int t = lower_bound(tmp + 1,tmp + N + 2,2 * A[i] + 1) - tmp - 1; while(1) { if(2 * sum[t] >= tmp[N]) {++ans;break;} int p = lower_bound(tmp + 1,tmp + N + 2,sum[t] * 2 + 1) - tmp - 1; if(p == t) break; t = p; } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意是給出一張圖,而後建一張新圖,新圖的點標號是(a,b)
若是a和c有一條邊,b和d有一條邊,那麼(a,b)和(c,d)之間有一條邊ui
咱們把這道題當成這道題來作,給出兩張圖,若是第一張圖有邊(a,c),第二張圖有邊(b,d),那麼第三張圖上有邊(a,b)(c,d)this
若是某張圖只有一個點,那麼答案就是另外一張圖的點數spa
而後咱們發現對於某兩個點對第一張圖(a,c),第二張圖(b,d)若是有一條長度爲L的路徑,那麼第三張圖(a,b)(c,d)必定能夠聯通
可是咱們發現咱們通過的路徑能夠不是簡單路徑,也就是咱們反覆走一條邊,那麼咱們只和路徑長度的奇偶性有關了code
很容易想到二分圖,若是兩張圖都是二分圖且聯通的話,那麼第三張圖聯通份量的個數是2
分別是\(S_a * T_b \cup T_a * S_b\)和\(S_a * S_b \cup T_a * T_b\)ci
而兩張圖都是非二分圖且聯通的話,任意路徑的奇偶性均可以互相轉化,因此整張圖就是一個聯通塊
那麼咱們求出兩個圖的孤立點個數\(i_A,i_B\),兩個圖的非二分圖聯通塊個數\(p_A,p_B\),兩個圖的二分圖聯通塊個數\(q_A,q_B\)
答案就是
\(i_Ai_B + i_A(N_B - i_B) + i_B(N_A - i_A) + p_Ap_B + p_Aq_B + p_Bq_A + 2q_Aq_B\)get
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <set> #include <cmath> #include <bitset> #include <queue> #define enter putchar('\n') #define space putchar(' ') //#define ivorysi #define pb push_back #define mo 974711 #define pii pair<int,int> #define mp make_pair #define fi first #define se second #define MAXN 200005 #define eps 1e-12 using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 - '0' + c; c = getchar(); } res = 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,M,I,P,Q; struct node { int next,to; }E[MAXN * 2]; int head[MAXN],sumE,col[MAXN]; bool vis[MAXN]; void dfs(int u) { vis[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v]) { dfs(v); } } } bool paint(int u) { if(!col[u]) col[u] = 2; for(int i = head[u] ; i; i = E[i].next) { int v = E[i].to; if(!col[v]) {col[v] = col[u] ^ 1;if(!paint(v)) return false;} else if(col[v] == col[u]) return false; } return true; } void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } void Solve() { read(N);read(M); int u,v; for(int i = 1 ; i <= M ; ++i) { read(u);read(v); add(u,v);add(v,u); } for(int i = 1 ; i <= N ; ++i) { if(!head[i]) ++I; else if(!vis[i]){ dfs(i); if(paint(i)) ++Q; else ++P; } } int64 ans = 1LL * I * I + 2LL * I * (N - I); ans += 1LL * P * P + 2LL * P * Q + 2LL * Q * Q; out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
大意是n個管子排成一排,每一個管子有兩種狀態,A狀態是從某個方向進去,從原方向出來,B狀態是從某個方向進去,從另外一個方向出來
球通過一個A狀態的管子這個管子會馬上變成B狀態,通過一個B狀態的管子會馬上變成A狀態
往裏面扔K個球,問最後管子的狀態
咱們發現若是第一個管子是A的話,球會馬上彈出去
不然的話
若是第二個管子是B
那麼
A -> B
A A ->
若是第二個管子是A
A -> A
A <- B
B -> B
B A ->
也就是,每次操做後的狀態只與右邊第一個管子有關,而且最後一個管子必定是A
那麼操做能夠考慮成,刪掉第一個字符,後面的字符所有取反,而後再最後填上一個A
然而有K次,咱們發現起點移動N次以後就是循環了
若是N次以後是
BABABA...那麼這個形態不會變
若是N次以後是
ABABAB...
那麼以後的形態就是
BBABAB...
ABABAB...
這樣的循環了
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <set> #include <cmath> #include <bitset> #include <queue> #define enter putchar('\n') #define space putchar(' ') //#define ivorysi #define pb push_back #define mo 974711 #define pii pair<int,int> #define mp make_pair #define fi first #define se second #define MAXN 200005 #define eps 1e-12 using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 - '0' + c; c = getchar(); } res = 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 N,K,p = 1,num[MAXN],cnt,st; void Solve() { read(N);read(K); scanf("%s",s + 1); for(int i = 1 ; i <= N ; ++i) num[i] = s[i] - 'A'; st = num[1]; while(K--) { if(st == 0) {st ^= 1;num[p] ^= 1;} else { ++p;++cnt; st = num[p]; st ^= (cnt & 1); } if(p > N) break; } if(p <= N) { for(int i = p ; i <= N ; ++i) putchar('A' + (num[i] ^ (cnt & 1))); int t = N - (N - p + 1),c = (cnt - 1) & 1; while(t--) { putchar('A' + c); c ^= 1; } } else { if((cnt - 1) & 1) { for(int i = 1 ; i <= N ; ++i) putchar('A' + (i & 1)); } else { putchar('A' + (K & 1)); for(int i = 1 ; i < N ; ++i) putchar('A' + (i & 1)); } } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
咱們發現一個非降低的數字必定能夠用不超過九個1111111111...1111表示
那麼咱們能夠獲得這樣的一個式子,假如咱們用了k個數,那麼最多的話能夠是這樣的
\(N = \sum_{i = 1}^{9k} (10^{r_i} - 1) / 9\)
\(9N + 9k = \sum_{i = 1}^{9k} 10^{r_{i}}\)
咱們只要每次計算出9N + 9 ,9N + 18...,而後看看十進制下每一位的數字和有沒有超過9k,直接加的話最壞狀況是一次操做\(O(L)\)的,可是你們應該都有種直覺總的操做就是\(O(L)\)的……就是勢能分析啦,不太會證,就是一次長的進位事後以後不會再進位了。。。
複雜度\(O(lg N)\)
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <set> #include <cmath> #include <bitset> #include <queue> #define enter putchar('\n') #define space putchar(' ') //#define ivorysi #define pb push_back #define mo 974711 #define pii pair<int,int> #define mp make_pair #define fi first #define se second #define MAXN 200005 #define eps 1e-12 using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 - '0' + c; c = getchar(); } res = 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 Bignum { vector<int> v; int sum; Bignum operator = (string s) { v.clear(); sum = 0; for(int i = s.length() - 1 ; i >= 0 ; --i) { v.pb(s[i] - '0'); sum += s[i] - '0'; } return *this; } friend Bignum operator * (const Bignum &a,const int b) { int s = a.v.size(); Bignum c;c.v.clear(); for(int i = 0 ; i <= s ; ++i) c.v.pb(0); int g = 0; for(int i = 0 ; i < s ; ++i) { int x = a.v[i] * b + g; c.v[i] = x % 10; g = x / 10; } if(g) c.v[s] = g; for(int i = s ; i > 0 ; --i) { if(c.v[i] == 0) c.v.pop_back(); else break; } c.sum = 0;s = c.v.size(); for(int i = 0 ; i < s ; ++i) c.sum += c.v[i]; return c; } }A; string s; void Solve() { cin>>s; A = s; A = A * 9; int ans = 0; while(1) { int s = A.v.size(); int g = 9; for(int i = 0 ; i < s ; ++i) { if(!g) break; A.sum -= A.v[i]; int x = A.v[i] + g; A.v[i] = x % 10; A.sum += A.v[i]; g = x / 10; } if(g) A.v.pb(g),A.sum += g; ++ans; if(ans * 9 >= A.sum) break; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
若是認爲從0到N每一站休息時間是\(q_0,q_1,q_2...q_{N- 1}\)
而後咱們認爲從N到0每一站休息時間是\(p_0,p_1,p_2...p_{N - 1}\)
\((\sum_{i = 0}^{s - 1} q_i + \sum_{i = 0}^{s - 1}A_{i},\sum_{i = 0}^{s - 1} q_i + \sum_{i = 0}^{s}A_{i})\)
這是從第s - 1站走到第s站的時間段
\((N - \sum_{i = 0}^{s - 1} p_i - \sum_{i = 0}^{s}A_{i},N - \sum_{i = 0}^{s - 1} p_i - \sum_{i = 0}^{s - 1}A_{i})\)
咱們要這兩個區間沒有交集
因爲取模k意義下,最後只要知足
\(\sum_{i = 0}^{s - 1}p_{i} + q_i \notin (-2\sum_{i = 0}^{s}A_{i},-2\sum_{i = 0}^{s - 1}A{i})\)
最後就變成,對於每一個單行道,咱們要求座標取模的值在某個區間內
設\(dpL[i]\)是i的時候在\(L[i]\)的位置上以後還要走多遠,\(dpR[i]\)同理
從後往前更新,每次找\(L[i]\)不在區間\([L[j],R[j]]\)的一個最小的j
而後用\(dpL[j]\)和\(dpR[j]\)更新
線段樹優化
而後能夠當答案的\(dpL[i]\)要求\(L[i]\)在\(1-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 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; int64 K,A[MAXN],sum[MAXN]; int B[MAXN],tot; int64 L[MAXN],R[MAXN],dpL[MAXN],dpR[MAXN],val[MAXN]; struct node { int l,r; int mx,lz; }tr[MAXN * 4]; int id; void update(int u) { if(!id) tr[u].mx = min(tr[u << 1].mx,tr[u << 1 | 1].mx); else tr[u].mx = max(tr[u << 1].mx,tr[u << 1 | 1].mx); } void addlz(int u,int v) { tr[u].lz = v; tr[u].mx = 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 build(int u,int l,int r,int v) { tr[u].l = l;tr[u].r = r;tr[u].lz = 0; if(l == r) { tr[u].mx = v; return; } int mid = (l + r) >> 1; build(u << 1,l,mid,v); build(u << 1 | 1,mid + 1,r,v); update(u); } void cover(int u,int l,int r,int v) { if(l > r) return; 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) cover(u << 1,l,r,v); else if(l > mid) cover(u << 1 | 1,l,r,v); else {cover(u << 1,l,mid,v);cover(u << 1 | 1,mid + 1,r,v);} update(u); } int query(int u,int l,int r) { if(l > r) return N + 1; if(tr[u].l == l && tr[u].r == r) return tr[u].mx; 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 { if(!id) return min(query(u << 1,l,mid),query(u << 1 | 1,mid + 1,r)); else return max(query(u << 1,l,mid),query(u << 1 | 1,mid + 1,r)); } } int64 dist(int64 A,int64 B) { if(B >= A) return B - A; else return K - (A - B); } void Solve() { read(N);read(K); for(int i = 1 ; i <= N ; ++i) { read(A[i]);read(B[i]); sum[i] = sum[i - 1] + A[i]; if(B[i] == 1) { if(2 * A[i] > K) {puts("-1");return;} L[i] = (-2 * sum[i - 1] % K + K) % K; R[i] = (-2 * sum[i] % K + K) % K; val[++tot] = L[i];val[++tot] = R[i]; } } sort(val + 1,val + tot + 1); tot = unique(val + 1,val + tot + 1) - val - 1; id = 0; build(1,1,tot,N + 1); for(int i = N ; i >= 1 ; --i) { if(B[i] == 1) { int l = lower_bound(val + 1,val + tot + 1,L[i]) - val; int r = lower_bound(val + 1,val + tot + 1,R[i]) - val; int t = query(1,l,l); if(t == N + 1) dpL[i] = 0; else dpL[i] = min(dpL[t] + dist(L[i],L[t]),dpR[t] + dist(L[i],R[t])); t = query(1,r,r); if(t == N + 1) dpR[i] = 0; else dpR[i] = min(dpR[t] + dist(R[i],R[t]),dpL[t] + dist(R[i],L[t])); if(l <= r) {cover(1,1,l - 1,i);cover(1,r + 1,tot,i);} else {cover(1,r + 1,l - 1,i);} } } id = 1; build(1,1,tot,0); int64 ans = 1e18; for(int i = 1 ; i <= N ; ++i) { if(B[i] == 1) { int l = lower_bound(val + 1,val + tot + 1,L[i]) - val; int r = lower_bound(val + 1,val + tot + 1,R[i]) - val; int t = query(1,l,l); if(t == 0) ans = min(ans,dpL[i]); t = query(1,r,r); if(t == 0) ans = min(ans,dpR[i]); if(l <= r) {cover(1,1,l - 1,i);cover(1,r + 1,tot,i);} else {cover(1,r + 1,l - 1,i);} } } ans += 2 * sum[N]; out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }