A Absolute
B Counting Permutations
C Cover
D Game
#include <cstdio>
using namespace std;
int main()
{
int n;
while(~scanf("%d", &n)) printf("Yes
");
}
E Hack It
构造一个矩阵,使得任何子矩阵的四个角不能都为1。
#include<cstdio> using namespace std; const int n = 47; const int maxn = 3010; int mp[maxn][maxn];
int main() { for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) mp[i*n+j][k*n+(j*k+i)%n]=1; printf("2000 "); for(int i=0;i<2000;i++) { for(int j=0;j<2000;j++) printf("%d", mp[i][j]); puts(""); } return 0; }
F Matrix
G Naive Operations
用线段树维护每个点被操作了多少次,然后当操作次数是b[i]的整数倍时,将sum[i]++。
新学了一种线段树的写法。
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
#define LL long long
const int maxn = 100000 + 10;
struct Sect
{
int cnt, lz;
LL sum;
}t[4*maxn];
int n, a[maxn], lim[maxn];
void build(int id, int l, int r)
{
t[id].lz = 0;
t[id].sum = 0;
if (l == r)
{
t[id].cnt = lim[l];
return;
}
int mid = (l+r) / 2;
build(id*2, l, mid);
build(id*2+1, mid+1, r);
t[id].sum = t[id*2].sum + t[id*2+1].sum;
t[id].cnt = min(t[id*2].cnt, t[id*2+1].cnt);
}
void push_down(int id)
{
if (t[id].lz)
{
t[id*2].lz += t[id].lz, t[id*2+1].lz += t[id].lz;
t[id*2].cnt -= t[id].lz, t[id*2+1].cnt -= t[id].lz;
t[id].lz = 0;
}
}
void update_range(int id, int L, int R, int l, int r)
{
if (t[id].cnt > 1 && L <= l && r <= R)
{
t[id].lz++;
t[id].cnt--;
return;
}
if (t[id].cnt == 1 && l == r)
{
t[id].sum++;
t[id].lz = 0;
t[id].cnt = lim[l];
return;
}
int mid = (l + r) / 2;
push_down(id);
if (L <= mid) update_range(id*2, L, R, l, mid);
if (R > mid) update_range(id*2+1, L, R, mid+1, r);
t[id].cnt = min(t[id*2].cnt, t[id*2+1].cnt);
t[id].sum = t[id*2].sum + t[id*2+1].sum;
}
LL query(int id, int L, int R, int l, int r)
{
if (L <= l && r <= R) return t[id].sum;
int mid = (l + r) / 2;
LL ans = 0;
push_down(id);
if (L <= mid) ans += query(id*2, L, R, l, mid);
if (R > mid) ans += query(id*2+1, L, R, mid+1, r);
t[id].cnt = min(t[id*2].cnt, t[id*2+1].cnt);
t[id].sum = t[id*2].sum + t[id*2+1].sum;
return ans;
}
int main()
{
int n, q;
while(scanf("%d%d", &n, &q) != EOF)
{
for (int i = 1; i <= n; i++) scanf("%d", &lim[i]);
build(1, 1, n);
char op[maxn];
int x, y;
for (int i = 1; i <= q; i++)
{
scanf("%s%d%d", op, &x, &y);
if (op[0] == 'a') update_range(1, x, y, 1, n);
else printf("%lld
", query(1, x, y, 1, n));
}
}
}
H Odd Shops
I Segment
J Swaps and Inversions
ans = 逆序对的数量 × min(x, y)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 100;
LL cnt = 0;
int T[maxn], a[maxn];
void merge_sort(int *A, int x, int y, int *T)
{
if (y-x > 1)
{
int m = x + (y-x)/2;
int p = x, q = m, i = x;
merge_sort(A, x, m, T);
merge_sort(A, m, y, T);
while(p < m || q < y)
{
if (q >= y || (p < m && A[p] <= A[q])) T[i++] = A[p++];
else T[i++] = A[q++], cnt += m-p;
}
for (i = x; i < y; i++) A[i] = T[i];
}
}
int main()
{
int n, x, y;
while(~scanf("%d%d%d", &n, &x, &y))
{
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
cnt = 0;
merge_sort(a, 1, n+1, T);
LL ans = cnt * min(x, y);
printf("%lld
", ans);
}
}