【AtCoder】AGC013
AGC013
A - Sorted Arrays
直接分就行
#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];
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) read(a[i]);
int f = 0;
int ans = N;
for(int i = 2 ; i <= N ; ++i) {
if(!f) {
if(a[i] > a[i - 1]) f = 1;
else if(a[i] < a[i - 1]) f = -1;
--ans;
}
else {
if(a[i] > a[i - 1] && f == 1) --ans;
else if(a[i] < a[i - 1] && f == -1) --ans;
else if(a[i] == a[i - 1]) --ans;
else f = 0;
}
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
B - Hamiltonish Path
直接一条路扩展到不能扩展位置
#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 N,M,head[MAXN],sumE;
int que[MAXN * 2],ql,qr;
bool vis[MAXN];
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 a,b;
for(int i = 1 ; i <= M ; ++i) {
read(a);read(b);
add(a,b);add(b,a);
}
ql = N,qr = N - 1;
que[++qr] = 1;vis[1] = 1;
while(1) {
int u = que[qr];
bool flag = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(!vis[v]) {
que[++qr] = v;
vis[v] = 1;
flag = 0;break;
}
}
if(flag) break;
}
while(1) {
int u = que[ql];
bool flag = 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(!vis[v]) {
que[--ql] = v;
vis[v] = 1;
flag = 0;break;
}
}
if(flag) break;
}
out(qr - ql + 1);enter;
for(int i = ql ; i <= qr ; ++i) {
out(que[i]);space;
}
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
C - Ants on a Circle
显然可以求出所有蚂蚁最后的位置,现在要确定第一个人的位置
逆时针转,撞一下编号减一,顺时针转,撞一下编号加一,模拟一下即可
#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 T,x[MAXN],to[MAXN],ans[MAXN],L;
int id[MAXN],w[MAXN];
void Solve() {
read(N);read(L);read(T);
for(int i = 0 ; i < N ; ++i) {
read(x[i]);read(w[i]);
if(w[i] == 1) to[i] = (x[i] + T) % L;
else to[i] = ((x[i] - T) % L + L) % L;
id[i] = i;
}
sort(id,id + N,[](int a,int b){return to[a] < to[b] || (to[a] == to[b] && w[a] < w[b]);});
int pos = 0;
for(int i = 1 ; i < N ; ++i) {
if(w[i] ^ w[0]) {
pos += (T / L) * 2 % N;
int64 rem = T % L;
int64 dis = x[i] - x[0];
if(w[0] == 2) dis = L - dis;
if(dis + L < 2 * rem) pos += 2;
else if(dis < 2 * rem) pos += 1;
pos %= N;
}
}
if(w[0] == 1) pos %= N;
else pos = (N - pos % N) % N;
for(int i = 0 ; i < N ; ++i) {
if(id[i] == 0) {
int p = i;
int cnt = 0;
while(cnt < N) {
ans[pos] = to[id[p]];
p = (p + 1) % N;
pos = (pos + 1) % N;
++cnt;
}
}
}
for(int i = 0 ; i < N ; ++i) {
out(ans[i]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
D - Piling Up
假如现在盒子里有\(x\)个红球,\(N - x\)个蓝球
\(dp[i][x]\)表示前\(2i\)个放完之后盒子里有\(x\)个红球
然后有四种
\(RR\),要求\(x > 0\),然后x - 1
\(RB\),要求\(x > 0\),然后x不变
\(BB\),要求\(x < N\),然后x + 1
\(BR\),要求\(x < N\),然后x不变
为了不重复统计,可以直接设置一个临近底部的特殊标记,如果这个操作序列画出的x变化图像不能下移才记录
#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 MOD = 1000000007;
int dp[3005][3005][2];
int N,M;
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);read(M);
for(int i = 0 ; i <= N ; ++i) dp[0][i][0] = 1;
for(int i = 0 ; i < M ; ++i) {
for(int j = 0 ; j <= N ; ++j) {
for(int k = 0 ; k <= 1 ; ++k) {
if(!dp[i][j][k]) continue;
if(j >= 1) {
int t = 0;
if(j == 1) t = 1;
update(dp[i + 1][j - 1][k | t],dp[i][j][k]);
update(dp[i + 1][j][k | t],dp[i][j][k]);
}
if(j <= N - 1) {
int t = 0;
if(j == 0) t = 1;
update(dp[i + 1][j + 1][k | t],dp[i][j][k]);
update(dp[i + 1][j][k | t],dp[i][j][k]);
}
}
}
}
int ans = 0;
for(int j = 0 ; j <= N ; ++j) update(ans,dp[M][j][1]);
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
E - Placing Squares
平方和转有序对
直接统计\(dp[x][i = 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 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 MOD = 1000000007;
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);
}
struct Matrix {
int f[3][3];
Matrix() {memset(f,0,sizeof(f));}
friend Matrix operator * (const Matrix &a,const Matrix &b) {
Matrix c;
for(int i = 0 ; i < 3 ; ++i) {
for(int j = 0 ; j < 3 ; ++j) {
for(int k = 0 ; k < 3 ; ++k) {
update(c.f[i][j],mul(a.f[i][k],b.f[k][j]));
}
}
}
return c;
}
void unit() {
for(int i = 0 ; i < 3 ; ++i) f[i][i] = 1;
}
}A,B,ans;
int N,M,x[MAXN];
Matrix fpow(Matrix a,int c) {
Matrix res,t = a;
res.unit();
while(c) {
if(c & 1) res = res * t;
t = t * t;
c >>= 1;
}
return res;
}
void Solve() {
read(N);read(M);
ans.unit();
A.f[0][1] = 2;A.f[0][2] = 1;A.f[0][0] = 1;
A.f[1][2] = 1;A.f[1][1] = 1;
A.f[2][2] = 2;A.f[2][0] = 1;A.f[2][1] = 2;
B = A;B.f[2][0] = 0;B.f[2][1] = 0;B.f[2][2] = 1;
int p = 0;
for(int i = 1 ; i <= M ; ++i) {
read(x[i]);
ans = ans * fpow(A,x[i] - p);
ans = ans * B;
p = x[i] + 1;
}
ans = ans * fpow(A,N - p);
out(ans.f[0][2]);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
F - Two Faced Cards
离散化之后把\([C[i],tot]\)减1
然后把正面的\([A[i],tot]\)加1
然后序列中不能有小于0的数,因为我们最后还能加上一张卡,在这之前我们需要满足所有的负值大于等于-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 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,Q,pos;
int A[MAXN][2],C[MAXN],ans;
int val[MAXN * 4],tot;
int cnt[MAXN * 4],num[MAXN * 4],f[MAXN * 4],inx[MAXN * 4];
bool all_fail;
struct cmp1 {
bool operator () (pii a,pii b) {
if(a.fi != b.fi) return a.fi < b.fi;
return a.se > b.se;
}
};
struct cmp2 {
bool operator () (pii a,pii b) {
if(a.se != b.se) return a.se > b.se;
return a.fi < b.fi;
}
};
multiset<pii,cmp1> S1;
multiset<pii,cmp2> S2;
vector<int> v[MAXN * 4];
vector<pii > rec;
void Init() {
read(N);
for(int i = 1 ; i <= N ; ++i) {
read(A[i][0]);read(A[i][1]);
val[++tot] = A[i][0];
val[++tot] = A[i][1];
}
for(int i = 1 ; i <= N + 1 ; ++i) {
read(C[i]);
val[++tot] = C[i];
}
sort(val + 1,val + tot + 1);
tot = unique(val + 1,val + tot + 1) - val - 1;
for(int i = 1 ; i <= N ; ++i) {
int t = lower_bound(val + 1,val + tot + 1,A[i][0]) - val;
cnt[t]++;
}
for(int i = 1 ; i <= N + 1 ; ++i) {
int t = lower_bound(val + 1,val + tot + 1,C[i]) - val;
cnt[t]--;
}
for(int i = 1 ; i <= tot ; ++i) {
num[i] = cnt[i];
cnt[i] += cnt[i - 1];
}
ans = N;
for(int i = 1 ; i <= N ; ++i) {
if(A[i][0] > A[i][1]) {
int s = lower_bound(val + 1,val + tot + 1,A[i][0]) - val;
int t = lower_bound(val + 1,val + tot + 1,A[i][1]) - val;
v[s - 1].pb(t);
}
}
int pre = 0;
memset(inx,0,sizeof(inx));
for(int i = tot ; i >= 1 ; --i) {
for(auto s : v[i]) S1.insert(mp(s,i));
pre += inx[i];
cnt[i] += pre;
while(cnt[i] < -1 && S1.size() > 0) {
pii seg = *S1.begin();S1.erase(S1.begin());
if(seg.fi > i) {rec.pb(seg);continue;}
num[seg.fi]++;num[seg.se + 1]--;
inx[seg.fi - 1]--;
--ans;
cnt[i]++;++pre;
}
if(cnt[i] < -1) all_fail = 1;
}
for(int i = 1 ; i <= tot ; ++i) {
num[i] += num[i - 1];
v[i].clear();
}
for(auto t : S1) {
rec.pb(t);
}
for(auto t : rec) {
v[t.fi].pb(t.se);
}
memset(inx,0,sizeof(inx));
pre = 0;
for(int i = 1 ; i <= tot ; ++i) {
for(auto t : v[i]) S2.insert(mp(i,t));
pre += inx[i];
num[i] += pre;
if(num[i] == -1) {
if(S2.size() <= 0) {
for(int j = i ; j <= tot ; ++j) f[j] = -1;
break;
}
pii seg = *S2.begin();
if(seg.se < i) {
for(int j = i ; j <= tot ; ++j) f[j] = -1;
break;
}
inx[seg.se + 1]--;
++pre;
f[i] = f[i - 1] + 1;
}
else f[i] = f[i - 1];
}
f[tot + 1] = -1;
}
void Solve() {
int Q;
read(Q);
int d,e;
for(int i = 1 ; i <= Q ; ++i) {
read(d);read(e);
if(all_fail) {puts("-1");continue;}
int res = -1;
int t = lower_bound(val + 1,val + tot + 1,d) - val - 1;
if(val[t - 1] == d - 1) {
if(f[t - 1] != -1) res = max(ans - f[t - 1] + 1,res);
}
if(f[t] != -1) res = max(ans - f[t] + 1,res);
t = lower_bound(val + 1,val + tot + 1,e) - val - 1;
if(val[t - 1] == e - 1) {
if(f[t - 1] != -1) res = max(ans - f[t - 1],res);
}
if(f[t] != -1) res = max(ans - f[t],res);
out(res);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}