【AtCoder】AGC011
AGC011
A - Airport Bus
大意:有N個人,每個人只能在\([T_i,T_i +K]\)這段區間乘車,每輛車安排C人,問最少安排幾輛車
直接掃,遇到一個沒有車的在\(T_i +K\)分配一輛
#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(); }
B - Colorful Creatures
大意:N個怪獸顏色兩兩不同,兩個怪物如果一個大小是A顏色是B,一個大小是C(C <= 2 * A)顏色是D,新怪物可以是大小A+C,顏色是B,問最後可能是幾種顏色
直接二分找滿足要求的數的位置,然後能擴到的最大體積就是從最小的數到這個數的前綴和,每次至少擴大兩倍,所以只用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(); }
C - Squared Graph
大意是給出一張圖,然後建一張新圖,新圖的點標號是(a,b)
如果a和c有一條邊,b和d有一條邊,那麽(a,b)和(c,d)之間有一條邊
我們把這道題當成這道題來做,給出兩張圖,如果第一張圖有邊(a,c),第二張圖有邊(b,d),那麽第三張圖上有邊(a,b)(c,d)
如果某張圖只有一個點,那麽答案就是另一張圖的點數
然後我們發現對於某兩個點對第一張圖(a,c),第二張圖(b,d)如果有一條長度為L的路徑,那麽第三張圖(a,b)(c,d)一定可以聯通
但是我們發現我們經過的路徑可以不是簡單路徑,也就是我們反復走一條邊,那麽我們只和路徑長度的奇偶性有關了
很容易想到二分圖,如果兩張圖都是二分圖且聯通的話,那麽第三張圖聯通分量的個數是2
而兩張圖都是非二分圖且聯通的話,任意路徑的奇偶性都可以互相轉化,所以整張圖就是一個聯通塊
那麽我們求出兩個圖的孤立點個數\(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\)
代碼
#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();
}
D - Half Reflector
大意是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();
}
E - Increasing Numbers
我們發現一個非下降的數字一定可以用不超過九個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();
}
【AtCoder】AGC011