大意:有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(); }