2020 黑龙江省赛
https://codeforces.com/gym/102803
A: August
猜结论的题目,nt
B:Bills of Paradise
线段树 四种操作:
1、查询区间第一个比x大的数
2、删除区间第一个比x大的数
3、区间所有小于x的数求和
4、将区间所有原来小于x的数还原
显然权值线段树维护区间最大值可以实现 1和2功能
可以通过维护区间和与区间最小值最大值实现 3功能
通过数组记录建树时整棵树的状态可以实现 4功能 通过lz标记可以优化
const int maxn = 1e6 + 10;
unsigned long long k1, k2;
unsigned long long xorShift128Plus() {
unsigned long long k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3 << 23;
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}
int n, m;
long long a[1000001], b[maxn], v[maxn];
char s[3];
struct seg{
int t[maxn << 2], sum[maxn << 2], tv[maxn << 2], ts[maxn << 2], mx[maxn << 2], mn[maxn << 2];
bool lz[maxn << 2];
#define root 1, 1, m
#define node rt, l, r
#define lr rt << 1
#define rr rt << 1 | 1
#define mid (l + r >> 1)
#define lson lr, l, mid
#define rson rr, mid + 1, r
inline void push(int rt) {
t[rt] = t[lr] + t[rr];
sum[rt] = sum[lr] + sum[rr];
mx[rt] = max(mx[lr], mx[rr]);
mn[rt] = min(mn[lr], mn[rr]);
}
inline void upd(int rt, int l, int r) {
lz[rt] = 1;
t[rt] = tv[rt];
sum[rt] = ts[rt];
mx[rt] = b[r];
mn[rt] = b[l];
}
inline void down(int rt, int l, int r) {
lz[rt] = 0;
upd(lson); upd(rson);
}
void build(int rt, int l, int r) {
if(l == r) {
tv[rt] = t[rt] = v[l];
ts[rt] = sum[rt] = b[l] * v[l];
mx[rt] = mn[rt] = b[l];
return ;
}
build(lson); build(rson);
tv[rt] = tv[lr] + tv[rr];
ts[rt] = ts[lr] + ts[rr];
push(rt);
}
int queryup(int rt, int l, int r, int x) {
if(l == r) return b[l];
if(lz[rt]) down(node);
if(mx[lr] >= x) return queryup(lson, x);
else if(mx[rr] >= x) return queryup(rson, x);
return 1e12;
}
int querysum(int rt, int l, int r, int x) {
if(mn[rt] > x) return 0;
if(mx[rt] <= x) return sum[rt];
if(lz[rt]) down(node);
return querysum(lson, x) + querysum(rson, x);
}
void reinit(int rt, int l, int r, int x) {
//printf("%lld %lld %lld %lld %lld\n", rt, l, r, b[l], b[r]);
if(b[l] > x) return ;
if(b[r] <= x) {
upd(node);
return ;
}
if(lz[rt]) down(node);
else {
reinit(lson, x);
reinit(rson, x);
}
push(rt);
}
void change(int rt, int l, int r, int x) {
if(l == r) {
t[rt] --; sum[rt] -= b[l];
if(t[rt] == 0) mx[rt] = 0, mn[rt] = 0x3f3f3f3f3f3f3f3f;
return ;
}
if(lz[rt]) down(node);
if(mx[lr] >= x) change(lson, x);
else if(mx[rr] >= x) change(rson, x);
push(rt);
}
}T;
void gen() {
scanf("%d %llu %llu", &n, &k1, &k2);
for (int i = 1; i <= n; i++) {
a[i] = xorShift128Plus() % 999999999999 + 1;
}
sort(a + 1, a + 1 + n); m = 1; int sum = 0;
for(int i = 1; i <= n; ++ i) {
v[m] ++; sum += a[i];
if(a[i] != a[i + 1]) b[m++] = a[i];
} m--;
T.build(root);
//for(int i = 1; i <= m; ++ i) printf("%lld%c", b[i], " \n"[i == m]);
int q = rd();
//printf("%lld %lld\n", T.querysum(root, 1e13), sum);
for(int i = 1; i <= q; ++ i) {
scanf("%s", s); int x = rd();
if(s[0] == 'F') printf("%lld\n", T.queryup(root, x));
else if(s[0] == 'D') T.change(root, x);
else if(s[0] == 'C') printf("%lld\n", T.querysum(root, x));
else T.reinit(root, x);
//printf("%lld\n", T.querysum(root, 1e12));
}
}
signed main() {
gen();
return 0;
}
C: Cornelia Street
超级无敌大水题,看起来什么循环节好像要kmp,复杂度都算不出来,结果暴力枚举N^2随便过
const int maxn = 1e6 + 10;
int n, m, len, pos;
char s[maxn];
bool ok(int l, int &pos) {
int nowpos = -1; pos = -1;
for(int i = l; i < len; ++ i) if(s[i % l] != s[i]) {
pos = i - i % l; break;
}
if(pos == -1 || pos + 2 * l > len) return 0;
for(int i = pos + l; i < len; ++ i) if(s[pos + i % l] != s[i]) {
nowpos = i - i % l; if(nowpos + l > len) return 0;
for(int j = nowpos; j < len; ++ j) if(s[j % l] != s[j]) return 0;
break;
}
if(nowpos == -1) return 0;
return 1;
}
signed main() {
scanf("%s", s); len = strlen(s);
for(int i = 1, up = len / 3; i <= up; ++ i) {
if(ok(i, pos)) {
for(int j = 0; j < i; ++ j) printf("%c", s[j]); printf(" ");
for(int j = 0; j < i; ++ j) printf("%c", s[j + pos]); puts("");
return 0;
}
}
return 0;
}
F:False God
nt dp
读题以为是互吃,我的回合碰到你就能吃你
实际上是只要小兵碰到你就会被吃,不管是你主动还是被动,那直接按位置排序,n^2dp暴力转移状态
struct node{
int x, y;
bool operator < (const node &a) const {
return y == a.y ? x < a.x : y > a.y;
}
}a[maxn];
int dp[maxn];
signed main() {
int t = rd();
while(t--) {
int sx = rd(), sy = rd();
int n = rd();
for(int i = 1; i <= n; ++ i) a[i].x = rd(), a[i].y = rd();
sort(a + 1, a + 1 + n); //puts("");
for(int i = 1; i <= n; ++ i) {
dp[i] = 1; // printf("%lld %lld\n", a[i].x, a[i].y);
for(int j = 1; j < i; ++ j) {
if(abs(a[i].x - a[j].x) - 1 <= a[j].y - a[i].y) dp[i] = max(dp[i], dp[j] + 1);
}
}
int ans = 0;
//for(int i = 1; i <= n; ++ i) printf("%lld%c", dp[i], " \n"[i == n]);
for(int i = 1; i <= n; ++ i) if(sy <= a[i].y + 1 && abs(sx - a[i].x) - 1 <= a[i].y - sy) ans = max(ans, dp[i]);
printf("%lld\n", ans);
}
return 0;
}
G: Goodbye
简单思维题
H:Hate That You Know Me
给\(k\in(0,1,2,3)\),求
\[\sum_{i = 1}^n \sum_{d|i}d^k
\]
显然转化为整除分块,\(d^k\) 通过公式O(1)求
\(mod = 1<<64\)显然是unsigned long long 的自然溢出
const int mod = (1 << 64);
//n * n * (n + 1) * (n + 1) / 4
inline int sum(int sta, int n) {
if(sta == 3) {
if(n & 1) return (n + 1) / 2 * ((n + 1) / 2) * n * n;
else return n / 2 * (n / 2) * (n + 1) * (n + 1);
}
else if(sta == 2) {
if(n & 1) {
if(n % 3 == 0) return (n + 1) / 2 * (n / 3) * (2 * n + 1);
else if((n + 1) % 3 == 0) return (n + 1) / 6 * n * (2 * n + 1);
else return (n + 1) / 2 * n * ((2 * n + 1) / 3);
}
else {
if(n % 3 == 0) return n / 6 * (n + 1) * (2 * n + 1);
else if((n + 1) % 3 == 0) return (n + 1) / 3 * (n / 2) * (2 * n + 1);
else return (2 * n + 1) / 3 * (n / 2) * (n + 1);
}
}
else if(sta) {
if(n & 1) return (n + 1) / 2 * n;
else return n / 2 * (n + 1);
}
else return n;
}/*
inline int sum(int sta, int n) {
if(sta == 3) return n * n * (n + 1) * (n + 1) / 4;
else if(sta == 2) return (2 * n + 1) * (n) * (n + 1) / 6;
else if(sta) return n * (n + 1) / 2;
else return n;
}*/
inline void qmod(int &a) {
if(a >= mod) a -= mod;
}
void solve3() {//n * (n + 1) * (2n + 1) / 6
int a = rd(), b = rd(), n = rd();
int ans1 = 0, ans2 = 0;
for(int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans1 += n / l * (sum(a, r) - sum(a, l - 1));
ans2 += n / l * (sum(b, r) - sum(b, l - 1));
}
printf("%llu\n", ans1 ^ ans2);
}
signed main() {
solve3();
return 0;
}
K: Keeping A Secret
滚远点谢谢
L:Let's Get Married
找规律构造

浙公网安备 33010602011771号