Forever Young

2020.08.27考试解题报告

总结

今天考试就跟闹着玩一样,爆零了
别人都走了就只剩下我,我就没检查,然后 \(130->0\)
快乐死了,尼盟思乐



思路

T1

here

想法&&正解

爆搜,以为满分
然后因为一个变量 \(sum\) 写成 \(minn\) 然后就爆蛋了


T2

here

想法

没想法,考场没写,爆蛋了

正解

很奇怪,不明白正确性

%% zql 的题解

原题意中操作翻转任意连续 $k $ 盏灯可等价为

  1. 翻转 $1\sim k $ 盏灯
  2. 翻转距离为 $ k $ 的两盏灯(两次作一次)

操作 \(1\) 直接枚举
操作 \(2\) 中,可将灯分成 \(n/k\) 组,每组互不影响
若一组内熄灭的灯数为奇数,舍弃亮度最小的灯(偶数时可全打开)


T3

here

想法:

考试的时候打树剖做了一个小时发现自己读错题意了
然后我就傻逼以为树剖不能做,又去写树上差分,然后因为没取模爆蛋了
但是不知道为什么取模之后不是 \(40\) 而是 \(30\)……

正解:

树剖板子加点小技巧

\(x\) 的子树中,经过 \(i\) 的边有 \((siz[x] - siz[i]) \times siz[i]\) 条,证明略。
那么查询 \(x\) 子树的贡献就是:

\[\sum\limits_{i\in \text{x的子树}}w[i]\times(siz[x]-six[i])\times siz[i] \]

化简:

\[\begin{aligned}&\sum\limits_{i\in \text{x的子树}}w[i]\times(siz[x]-six[i])\times siz[i]\\=&\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]\times siz[x]-\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]^2\\=&siz[x]\times\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]-\sum\limits_{i\in\text{x的子树}}w[i]\times siz[i]^2\end{aligned} \]

只有 \(siz[x]\)\(x\) 有关,所以可以用线段树维护一个点 \(i\) 的贡献,查询的时候随便艹一下就能做了,详情看代码



代码

T1

考场代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 20;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
	char c = getchar();
	int x = 0, f = 1;
	for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
	return x * f;
}

int T, n, k, maxn, minn, tot, mmm;
int now[A], cnt, a[A], b[A];

void dfsmin(int k, int cnt) {
	if(k <= 0 || cnt >= tot) {
		int sum = 0;
		for (int i = 1; i <= tot; i++)
			sum = sum * 10 + a[i];
		if (minn >= mmm) minn = min(minn, sum);
		//debug:sum写成minn……100-->0 
		return;
	}
	for (int i = cnt + 1; i <= tot; i++)
		if (a[i] <= a[cnt]) {
			swap(a[i], a[cnt]);
			dfsmin(k - 1, cnt + 1);
			swap(a[i], a[cnt]);
		}
	dfsmin(k, cnt + 1);
}

void dfsmax(int k, int cnt) {
	if (k <= 0 || cnt >= tot) {
		int sum = 0;
		for (int i = 1; i <= tot; i++)
			sum = sum * 10 + b[i];
		maxn = max(maxn,sum);
		return;
	}
	for (int i = cnt + 1; i <= tot; i++)
		if (b[i] >= b[cnt]) {
			swap(b[i], b[cnt]);
			dfsmax(k - 1, cnt + 1);
			swap(b[i], b[cnt]);
		}
	dfsmax(k, cnt + 1);
}

inline void solve() {
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(now ,0, sizeof(now));
	cnt = tot = 0;
	n = read(), k = read();
	minn = inf, maxn = 0;
	while (n) now[++cnt] = n % 10, n /= 10;
	mmm = 1;
	for (int i = cnt; i; i--)
		a[++tot] = now[i], b[tot] = now[i], mmm *= 10;
	mmm /= 10;
	dfsmin(k, 1), dfsmax(k, 1);
	cout << maxn - minn << '\n';
}

signed main() {
	T = read();
	while (T--) solve();
	return 0;
}

正解

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 20;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
	char c = getchar();
	int x = 0, f = 1;
	for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
	return x * f;
}

int T, n, k, maxn, minn, tot, mmm;
int now[A], cnt, a[A], b[A];

void dfsmin(int k, int cnt) {
	if(k <= 0 || cnt >= tot) {
		int sum = 0;
		for (int i = 1; i <= tot; i++)
			sum = sum * 10 + a[i];
		if (sum >= mmm) minn = min(minn, sum);
		//debug:sum写成minn……100-->0 
		return;
	}
	for (int i = cnt + 1; i <= tot; i++)
		if (a[i] <= a[cnt]) {
			swap(a[i], a[cnt]);
			dfsmin(k - 1, cnt + 1);
			swap(a[i], a[cnt]);
		}
	dfsmin(k, cnt + 1);
}

void dfsmax(int k, int cnt) {
	if (k <= 0 || cnt >= tot) {
		int sum = 0;
		for (int i = 1; i <= tot; i++)
			sum = sum * 10 + b[i];
		maxn = max(maxn,sum);
		return;
	}
	for (int i = cnt + 1; i <= tot; i++)
		if (b[i] >= b[cnt]) {
			swap(b[i], b[cnt]);
			dfsmax(k - 1, cnt + 1);
			swap(b[i], b[cnt]);
		}
	dfsmax(k, cnt + 1);
}

inline void solve() {
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(now ,0, sizeof(now));
	cnt = tot = 0;
	n = read(), k = read();
	minn = inf, maxn = 0;
	while (n) now[++cnt] = n % 10, n /= 10;
	mmm = 1;
	for (int i = cnt; i; i--)
		a[++tot] = now[i], b[tot] = now[i], mmm *= 10;
	mmm /= 10;
	dfsmin(k, 1), dfsmax(k, 1);
	cout << maxn - minn << '\n';
}

signed main() {
	T = read();
	while (T--) solve();
	return 0;
}

T2

正解

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int A = 1e5 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar();
  int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

int n, k, zt[A], val[A], sum, ans, res;

inline void solve() {
  memset(zt, 0, sizeof(zt));
  memset(val, 0, sizeof(val));
  n = read(), k = read();
  sum = 0, ans = 0;
  for (int i = 1; i <= n; i++) zt[i] = read();
  for (int i = 1; i <= n; i++) val[i] = read(), sum += val[i];
  res = sum;
  for (int i = 1; i <= k; i++) {
    int cnt = 0, minn = inf;
    for (int j = i; j <= n; j += k) {
      if (!zt[j]) cnt++; 
      minn = min(val[j], minn);
    }
    if (cnt & 1) res -= minn;
  }
  ans = max(ans, res);
  for (int i = 1; i <= k; i++) zt[i] ^= 1;
  res = sum;
  for (int i = 1; i <= k; i++) {
    int cnt = 0, minn = inf;
    for (int j = i; j <= n; j += k) {
      if (!zt[j]) cnt++; 
      minn = min(val[j], minn);
    }
    if (cnt & 1) res -= minn;
  }
  ans = max(ans, res);
  cout << ans << '\n';
}

int main() {
  int T = read();
  while (T--) solve();
  return 0;
}

T3

考场代码(加个取模吧)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int mod = 2019;
const int A = 6e5 + 11;
const int B = 1e6 + 11;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar(); int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

int n, m, root, cnt, head[A], dis[A], ans = 0, val[A], nb[A];
int fa[A], dep[A], son[A], siz[A], c[A], top[A];
struct node { int to, nxt, val; } e[B << 1];

inline void add(int from, int to, int val) {
  e[++cnt].to = to;
  e[cnt].val = val;
  e[cnt].nxt = head[from];
  head[from] = cnt;
}

void prepare(int x, int f) {
  dep[x] = dep[f] + 1, siz[x] = 1, fa[x] = f;
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == f) continue;
    prepare(to, x), siz[x] += siz[to];
    if (siz[to] > siz[son[x]]) son[x] = to;
  }
}

void dfs(int x, int tp) {
  top[x] = tp;
  if (son[x]) dfs(son[x], tp);
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == fa[x] || to == son[x]) continue;
    dfs(to, to);
  }
}

inline int LCA(int x, int y) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]]) swap(x, y);
    x = fa[top[x]];
  }
  if (dep[x] > dep[y]) swap(x, y);
  return x;
}

void cnm(int x, int f) {
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == f) continue;
    cnm(to, x);
    (nb[x] += nb[to]) %= mod;
  }
}

void new_dfs(int x, int f, int now) {
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == f) continue;
    new_dfs(to, x, now);
    ans += (e[i].val + nb[to]) * (siz[now] - siz[to]) * siz[to], ans %= mod; 
  }
}

int main() {
  freopen("network.in", "r", stdin);
  freopen("network.out", "w", stdout);
  n = read(), m = read();
  for (int i = 2; i <= n; i++) {
    fa[i] = read(), c[i] = read();
    add(fa[i], i, c[i]), add(i, fa[i], c[i]);
  }
  root = n;
  while (fa[root]) root = fa[root];
  prepare(root, 0), dfs(root, root);
  char s[4];
  int x, y, w, flag = 0;
  while (m--) {
    scanf("%s", s);
    if (s[0] == 'I') {
      flag = 1;
      x = read(), y = read(), w = read();
      int lca = LCA(x, y);
      val[x] += w, val[y] += w, val[lca] -= 2 * w;
    }
    else if (s[0] == 'A') {
      x = read(); 
      if (flag) {
        for (int i = 1; i <= n; i++) nb[i] = val[i];
        cnm(root, 0);
      }
      ans = 0;
      new_dfs(x, fa[x], x);
      cout << ans % mod << '\n';
    }
  }
  return 0;
}

正解

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int mod = 2019;
const int A = 6e5 + 11;
const int B = 1e6 + 11;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar(); int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

int n, m, root, cnt, head[A];
struct node { int to, nxt, val; } e[B << 1];

inline void add(int from, int to, int val) {
  e[++cnt].to = to;
  e[cnt].val = val;
  e[cnt].nxt = head[from];
  head[from] = cnt;
}

int tot, fa[A], dep[A], son[A], siz[A], dfn[A], pre[A], c[A], top[A], w[A];

namespace Seg {
  #define lson rt << 1
  #define rson rt << 1 | 1
  struct tree { int l, r, sum1, sum2, lazy, siz1, siz2; } t[A << 2];
  //sum1 w[i] ×siz[i]
  //sum2 w[i] ×siz[i]^2
  
  inline void pushup(int rt) {
    t[rt].sum1 = (t[lson].sum1 + t[rson].sum1) % mod;
    t[rt].sum2 = (t[lson].sum2 + t[rson].sum2) % mod; 
  }
  
  inline void pushdown(int rt) {
    t[lson].lazy += t[rt].lazy, t[lson].lazy %= mod;
    t[rson].lazy += t[rt].lazy, t[rson].lazy %= mod;
    t[lson].sum1 += t[lson].siz1 * t[rt].lazy % mod, t[lson].sum1 %= mod;
    t[lson].sum2 += t[lson].siz2 * t[rt].lazy % mod, t[lson].sum2 %= mod;
    t[rson].sum1 += t[rson].siz1 * t[rt].lazy % mod, t[rson].sum1 %= mod;
    t[rson].sum2 += t[rson].siz2 * t[rt].lazy % mod, t[rson].sum2 %= mod;
    t[rt].lazy = 0;
  }
  
  void build(int rt, int l, int r) {
    t[rt].l = l, t[rt].r = r, t[rt].lazy = 0;
    if (l == r) { 
      t[rt].sum1 = w[pre[l]] * siz[pre[l]] % mod; 
      t[rt].sum2 = t[rt].sum1 * siz[pre[l]] % mod;
      t[rt].siz1 = siz[pre[l]] % mod;
      t[rt].siz2 = siz[pre[l]] * siz[pre[l]] % mod;
      return; 
    }
    int mid = (l + r) >> 1;
    build(lson, l, mid), build(rson, mid + 1, r);
    t[rt].siz1 = (t[lson].siz1 + t[rson].siz1) % mod;
    t[rt].siz2 = (t[lson].siz2 + t[rson].siz2) % mod;
    pushup(rt);
  }
  
  void update(int rt, int l, int r, int val) {
    if (l <= t[rt].l && t[rt].r <= r) {
      t[rt].sum1 = (t[rt].sum1 + t[rt].siz1 * val) % mod;
      t[rt].sum2 = (t[rt].sum2 + t[rt].siz2 * val) % mod;
      t[rt].lazy = (t[rt].lazy + val) % mod;
      return;
    }
    if (t[rt].lazy) pushdown(rt);
    int mid = (t[rt].l + t[rt].r) >> 1;
    if (l <= mid) update(lson, l, r, val);
    if (r > mid) update(rson, l, r, val);
    pushup(rt);
  }
  
  int query(int rt, int l, int r) {
    if (l <= t[rt].l && t[rt].r <= r) return t[rt].sum1 % mod;
    if (t[rt].lazy) pushdown(rt);
    int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
    if (l <= mid) ans += query(lson, l, r), ans %= mod;
    if (r > mid) ans += query(rson, l, r), ans %= mod;
    return ans;
  }
  
  int query2(int rt, int l, int r) {
    if (l <= t[rt].l && t[rt].r <= r) return t[rt].sum2 % mod;
    if (t[rt].lazy) pushdown(rt);
    int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
    if (l <= mid) ans += query2(lson, l, r), ans %= mod;
    if (r > mid) ans += query2(rson, l, r), ans %= mod;
    return ans;
  }
}

void prepare(int x, int f) {
  dep[x] = dep[f] + 1, siz[x] = 1, fa[x] = f;
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == f) continue;
    w[to] = e[i].val;
    prepare(to, x), siz[x] += siz[to];
    if (siz[to] > siz[son[x]]) son[x] = to;
  }
}

void dfs(int x, int tp) {
  dfn[x] = ++tot, pre[tot] = x, top[x] = tp;
  if (son[x]) dfs(son[x], tp);
  for (int i = head[x]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == fa[x] || to == son[x]) continue;
    dfs(to, to);
  }
}

inline void add_qwq(int x, int y, int val) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]]) swap(x, y);
    Seg::update(1, dfn[top[x]], dfn[x], val);
    x = fa[top[x]];
  }
  if (dep[x] > dep[y]) swap(x, y);
  Seg::update(1, dfn[x] + 1, dfn[y], val);
  return;
}

inline int ask_qwq(int x) {
  int ans1 = Seg::query(1, dfn[x] + 1, dfn[x] + siz[x] -1);
  int ans2 = Seg::query2(1, dfn[x] + 1, dfn[x] + siz[x] - 1);
  int ans = ans1 * siz[x] % mod - ans2;
  ans = (ans % mod + mod) % mod;
  return ans;
}

int main() {
  n = read(), m = read();
  for (int i = 2; i <= n; i++) {
    fa[i] = read(), c[i] = read();
    add(fa[i], i, c[i]), add(i, fa[i], c[i]);
  }
  root = 1;
  while (fa[root]) root = fa[root];
  prepare(root, 0), dfs(root, root), Seg::build(1, 1, n);
  char s[4];
  int x, y, w;
  while (m--) {
    scanf("%s", s);
    if (s[0] == 'I') x = read(), y = read(), w = read(), add_qwq(x, y, w);
    else if (s[0] == 'A') {
      x = read();
      if (x == 0) x = root;
      cout << ask_qwq(x) << '\n';
    }
  }
  return 0;
}
posted @ 2020-08-27 18:03  Loceaner  阅读(174)  评论(9编辑  收藏  举报