牛客练习赛26
C 城市规划
ps:想复杂了,记录每个点靠的最近的左端点和枚举到这个点时,上次切割的位置。(每次切割都切右端点)
namespace fastIO { #define BUF_SIZE 100000 bool IOerror = 0; inline char nc() { static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; if(p1 == pend) { p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin); if(pend == p1) { IOerror = 1; return -1; } } return *p1++; } inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; } inline void read(int &x) { char ch; while(blank(ch = nc())); if(IOerror) return; for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); } #undef BUF_SIZE }; using namespace fastIO; const int N = 1000005; int n, m; int a[N]; int main() { read(n); read(m); int l, r; Rep(i, 1, m) { read(l); read(r); if (a[r] < l) a[r] = l; } int ans = 0, cut = a[1]; Rep(i, 1, n) if (a[i]) { if (a[i] >= cut) { ans++; cut = i; } } pr(ans); return 0; }
D XOR序列
ps:x ^ ? = y,则 ? = x ^ y。所以问题转化为:这n个数的线性基能否表示出 ?。
int n, q; LL p[100]; void Insert(int x) { for (int i = 62; ~i; --i) if ((1 << i) & x) { if (!p[i]) { p[i] = x; break; } x ^= p[i]; } } bool check(int x) { for (int i = 62; ~i; --i) if ((x & (1 << i)) && p[i]) { x ^= p[i]; } return (x == 0); } int main() { sc(n); Rep(i, 1, n) { int x; sc(x); Insert(x); } sc(q); while(q--) { int x, y; sc(x), sc(y); if (check(x ^ y)) puts("YES"); else puts("NO"); } return 0; }
ps:设最短路径上的点的和为a,点的平方和为b,则 ans = (a * a — b) / 2。然后 a^2 和 b 分别用树剖+线段树维护就行了。注意取模 !!!!!!!!
const int N = 100005; const int mod = 1000000007; const int inv2 = 500000004; int n, m; int v[N], dep[N], pa[N], id[N], rk[N], sz[N], son[N], top[N]; struct BST { int cnt; int a[N * 4], b[N * 4], use[4 * N]; void Inite() { cnt = 0; mem(use, 0); } void Pushup(int root) { a[root] = (0ll + a[lson] + a[rson]) % mod; b[root] = (0ll + b[lson] + b[rson]) % mod; } void Pushdown(int l, int r, int root) { use[lson] = (0ll + use[lson] + use[root]) % mod; use[rson] = (0ll + use[rson] + use[root]) % mod; int mid = (l + r) >> 1; b[lson] = (0ll + b[lson] + 1ll * use[root] * use[root] % mod * (mid - l + 1) % mod + 2ll * use[root] * a[lson] % mod) % mod; b[rson] = (0ll + b[rson] + 1ll * use[root] * use[root] % mod * (r - mid) % mod + 2ll * use[root] * a[rson] % mod) % mod; a[lson] = (0ll + a[lson] + 1ll * (mid - l + 1) * use[root] % mod) % mod; a[rson] = (0ll + a[rson] + 1ll * (r - mid) * use[root] % mod) % mod; use[root] = 0; } void Build(int l, int r, int root) { if (l == r) { a[root] = v[rk[++cnt]]; b[root] = 1ll * a[root] * a[root] % mod; return; } int mid = (l + r) >> 1; Build(l, mid, lson); Build(mid + 1, r, rson); Pushup(root); } void Update(int l, int r, int root, int L, int R, int x) { if (l > R || r < L) return; if (L <= l && r <= R) { use[root] = (0ll + use[root] + x) % mod; b[root] = (0ll + b[root] + 1ll * x * x % mod * (r - l + 1) % mod + 2ll * x * a[root] % mod) % mod; a[root] = (0ll + a[root] + 1ll * x * (r - l + 1) % mod) % mod; return; } int mid = (l + r) >> 1; if (use[root]) Pushdown(l, r, root); Update(l, mid, lson, L, R, x); Update(mid + 1, r, rson, L, R, x); Pushup(root); } int Query(int l, int r, int root, int L, int R, bool flag) { if (l > R || r < L) return 0; if (L <= l && r <= R) { if (flag) return a[root]; else return b[root]; } if (use[root]) Pushdown(l, r, root); int mid = (l + r) >> 1; int ans = 0; ans = (0ll + ans + Query(l, mid, lson, L, R, flag)) % mod; ans = (0ll + ans + Query(mid + 1, r, rson, L, R, flag)) % mod; return ans; } }; BST T; struct TreeCut { int cnt; vector<int> G[N]; void Inite() { T.Inite(); cnt = 0; mem(son, -1); Rep(i, 0, n) G[i].clear(); } void addedge(int u, int v) { G[u].pb(v); G[v].pb(u); } void DFS1(int u, int p, int d) { pa[u] = p; sz[u] = 1; dep[u] = d; for (auto v : G[u]) if (v != p) { DFS1(v, u, d + 1); sz[u] += sz[v]; if (son[u] == -1 || sz[son[u]] < sz[v]) son[u] = v; } } void DFS2(int u, int st) { top[u] = st; id[u] = ++cnt; rk[cnt] = u; if (son[u] == -1) return; DFS2(son[u], st); for (auto v : G[u]) if (v != son[u] && v != pa[u]) DFS2(v, v); } void Start() { DFS1(1, 1, 0); DFS2(1, 1); T.Inite(); T.Build(1, n, 1); } void Update(int u, int v, int x) { int pu = top[u], pv = top[v]; while(pu != pv) { if (dep[pu] > dep[pv]) { T.Update(1, n, 1, id[pu], id[u], x); u = pa[pu]; } else { T.Update(1, n, 1, id[pv], id[v], x); v = pa[pv]; } pu = top[u], pv = top[v]; } if (id[u] <= id[v]) T.Update(1, n, 1, id[u], id[v], x); else T.Update(1, n, 1, id[v], id[u], x); } int sum(int u, int v) { int pu = top[u], pv = top[v]; int sa = 0, sb = 0; while(pu != pv) { if (dep[pu] > dep[pv]) { sa = (0ll + sa + T.Query(1, n, 1, id[pu], id[u], 1)) % mod; sb = (0ll + sb + T.Query(1, n, 1, id[pu], id[u], 0)) % mod; u = pa[pu]; } else { sa = (0ll + sa + T.Query(1, n, 1, id[pv], id[v], 1)) % mod; sb = (0ll + sb + T.Query(1, n, 1, id[pv], id[v], 0)) % mod; v = pa[pv]; } pu = top[u], pv = top[v]; } if (id[u] <= id[v]) { sa = (0ll + sa + T.Query(1, n, 1, id[u], id[v], 1)) % mod; sb = (0ll + sb + T.Query(1, n, 1, id[u], id[v], 0)) % mod; } else { sa = (0ll + sa + T.Query(1, n, 1, id[v], id[u], 1)) % mod; sb = (0ll + sb + T.Query(1, n, 1, id[v], id[u], 0)) % mod; } return (1ll * sa * sa % mod - 1ll * sb + mod) * (LL)inv2 % mod; } }; TreeCut cut; int main() { sc(n), sc(m); Rep(i, 1, n) sc(v[i]); cut.Inite(); rep(i, 1, n) { int u, v; sc(u), sc(v); cut.addedge(u, v); } cut.Start(); while(m--) { int op, x, y, z; sc(op); if (op == 1) { sc(x), sc(z); T.Update(1, n, 1, id[x], id[x] + sz[x] - 1, z); } else if (op == 2) { sc(x), sc(y), sc(z); cut.Update(x, y, z); } else { sc(x), sc(y); pr(cut.sum(x, y)); } } return 0; }