codeforces-1136 (div2)
A.读到第i章,就有N - i + 1章还没读。
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; PII a[maxn]; int main(){ Sca(N); for(int i = 1; i <= N ; i ++){ Sca2(a[i].fi,a[i].se); } K = read(); for(int i = 1; i <= N ; i ++){ if(a[i].fi <= K && K <= a[i].se){ Pri(N - i + 1); break; } } return 0; }
B.很显然,先把起始点的石头扔到一边,然后向离端点距离短的一边走,走到端点再想另一端走,途中一边取硬币,石头全扔到起始点。
推出式子显然
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; PII a[maxn]; int main(){ Sca2(N,K); Pri(2 + N + 2 * min(N - K,K - 1) + max(N - K,K - 1) + N - 1); return 0; }
C.发现对2 * 2的矩阵操作就是把斜相邻的两个数交换,其余N * M的矩阵操作都可以通过交换两个斜对角实现,所以交换只能交换左上右下这样一个斜对角。
那么判断两个矩阵的每个斜对角是否是相同的元素即可
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 510; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int A[maxn][maxn],B[maxn][maxn]; vector<int>a[maxn * 2],b[maxn * 2]; int main(){ Sca2(N,M); For(i,1,N) For(j,1,M) Sca(A[i][j]); For(i,1,N) For(j,1,M) Sca(B[i][j]); For(i,1,N) For(j,1,M){ a[i + j].pb(A[i][j]); b[i + j].pb(B[i][j]); } for(int i = 1; i <= N + M ; i ++){ sort(a[i].begin(),a[i].end()); sort(b[i].begin(),b[i].end()); if(a[i] != b[i]){ puts("NO"); return 0; } } puts("YES"); return 0; }
D.前面的u点可以和后面的v点交换称为u可以吃掉v,点i最终可以排到nastya的后面需要满足在他后面的点是自主排到nastya后面或者它可以被i吃掉。
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 3e5 + 10; const int maxm = 5e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int a[maxn]; int pos[maxn]; int pre[maxn]; struct Edge{ int to,next; }edge[maxm * 2]; int head[maxn],tot; void init(){ for(int i = 0 ; i <= N ; i ++) head[i] = -1; tot = 0; } void add(int u,int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } int main(){ Sca2(N,M); init(); for(int i = 1; i <= N ; i ++){ a[i] = read(); pos[a[i]] = i; } for(int i = 1; i <= M ; i ++){ PII e; e.fi = read(); e.se = read(); if(pos[e.fi] < pos[e.se]){ pre[pos[e.fi]]++; add(pos[e.se],pos[e.fi]); } } int ans = 0,now = 1; for(int i = N - 1; i >= 1; i --){ if(pre[i] == now){ ans++; for(int j = head[i]; ~j ; j = edge[j].next) pre[edge[j].to]--; }else{ now++; } } Pri(ans); return 0; }
E.对k求一个前缀和pre,对于u点,属于[u,N]之间的所有点i的最小值都会满足 a[x] >= a[u] + pre[i] - pre[u]
对于i来说,pre[i]是固定的,动态更新的是a[u] - pre[u],所以将pre[i]分离出来,线段树维护每个点的a[u] - pre[u],维护区间和以及最大最小值。
求区间和的时候就是ppre[r] - ppre[l - 1] + 线段树维护的l到r之间的和。
坑点:lazy标记不能打成0,需要设为-INF,因为a[u] - pre[u]可能是负数
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; LL read(){LL x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const LL INF = 1e18; const int mod = 1e9 + 7; int N,M,K; struct Tree{ int l,r; LL sum,MIN,MAX,lazy; }tree[maxn << 2]; LL a[maxn],pre[maxn],ppre[maxn]; void Pushup(int t){ tree[t].sum = tree[t << 1].sum + tree[t << 1 | 1].sum; tree[t].MIN = min(tree[t << 1].MIN,tree[t << 1 | 1].MIN); tree[t].MAX = max(tree[t << 1].MAX,tree[t << 1 | 1].MAX); } void Build(int t,int l,int r){ tree[t].l = l; tree[t].r = r; tree[t].lazy = -INF; if(l == r){ tree[t].MAX = tree[t].sum = tree[t].MIN = a[l] - pre[l]; return; } int m = l + r >> 1; Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r); Pushup(t); } void change(int t,LL p){ tree[t].lazy = max(p,tree[t].lazy); tree[t].sum = (tree[t].r - tree[t].l + 1) * p; tree[t].MAX = tree[t].MIN = p; } void Pushdown(int t){ if(tree[t].lazy != -INF){ change(t << 1,tree[t].lazy); change(t << 1 | 1,tree[t].lazy); tree[t].lazy = -INF; } } void update(int t,int l,int r,LL p){ if(tree[t].MIN >= p) return; if(l <= tree[t].l && tree[t].r <= r && tree[t].MAX <= p){ change(t,p); return; } Pushdown(t); int m = (tree[t].r + tree[t].l) >> 1; if(r <= m) update(t << 1,l,r,p); else if(l > m) update(t << 1 | 1,l,r,p); else{ update(t << 1,l,m,p); update(t << 1 | 1,m + 1,r,p); } Pushup(t); } LL query(int t,int l,int r){ if(l <= tree[t].l && tree[t].r <= r) return tree[t].sum; Pushdown(t); int m = (tree[t].l + tree[t].r) >> 1; if(r <= m) return query(t << 1,l,r); else if(l > m) return query(t << 1 | 1,l,r); else return query(t << 1,l,m) + query(t << 1 | 1,m + 1,r); } int main(){ Sca(N); for(int i = 1; i <= N ; i ++) a[i] = read(); for(int i = 2; i <= N; i ++){ pre[i] = read() + pre[i - 1]; ppre[i] = pre[i] + ppre[i - 1]; } Build(1,1,N); int Q; Sca(Q); while(Q--){ char op[3]; int l,r; scanf("%s%d%d",&op,&l,&r); if(op[0] == '+'){ LL x = query(1,l,l) + r + pre[l]; update(1,l,N,x - pre[l]); }else{ Prl(query(1,l,r) + ppre[r] - ppre[l - 1]); } } return 0; }