1010 sometiems naive
树链剖分。从根到任意节点的路径不超过 log2n 条轻链,因此,轻链可以单独维护。#define clr(A,x) memset(A,x,sizeof(A)) using namespace std; typedef long long LL; typedef pair<int,int> P; typedef pair<int,P> pp; typedef complex<double> cpx; const int mm = 1e5+5; const int mod = 1000000007; using namespace std; int n, m; int w[mm]; vector<int> g[mm]; LL sum = 0; void input() { for(int i = 1; i <= n; i++) { scanf("%d",w+i); } for(int i = 0; i <= n; i++) g[i].clear(); for(int i = 1; i < n; i++) { int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } } int fa[mm],sz[mm],hson[mm],top[mm]; int id[mm],idx,d[mm],di[mm]; void dfs_sz(int rt) { // sumw[rt] = w[rt]; sz[rt] = 1;d[rt] = d[fa[rt]]+1; int &son = hson[rt]; for(int i = 0; i < g[rt].size(); i++) if(g[rt][i] != fa[rt]){ int &u = g[rt][i]; fa[u] = rt; dfs_sz(u); sz[rt] += sz[u]; // sumw[rt] += sumw[u]; if(son == 0 || sz[son] < sz[u]) son = u; } } void dfs_chain(int rt,int anc) { id[rt] = ++idx;di[idx] = rt; top[rt] = anc; int &son = hson[rt]; if(son != 0) dfs_chain(son,anc); for(int i = 0; i < g[rt].size(); i++) { int &u = g[rt][i]; if(u == son || u == fa[rt]) continue; dfs_chain(u,u); } } int N; void modify(LL C[],int x,int dx) { for(x; x < N; x += x&(-x)) { C[x] = (C[x] + dx) % mod; // if(C[x] >= mod) C[x] -= mod; } } LL getsum(LL C[],int x) { LL res = 0; for(x;x > 0; x -= x&(-x)) { res = (res + C[x]) % mod; // if(res >= mod) res -= mod; } return res; } const int root = 1; LL C2[mm],C0[mm]; //LL A1[mm],A0[mm]; void change(int u,int uw) { // int v = root; // LL dx2 = (LL)uw*uw - (LL)w[u]*w[u]; LL dx1 = uw - w[u]; sum = (sum + dx1) % mod; // if(sum >= mod) sum -= mod; w[u] = uw; while(top[u] != root) { LL x = getsum(C0,id[top[u]]); LL dx2 = (x+dx1)*(x+dx1) % mod - x*x % mod; dx2 %= mod; modify(C2,id[fa[top[u]]],dx2); modify(C0,id[top[u]],dx1); modify(C0,id[u]+1,-dx1); u = fa[top[u]]; } modify(C0,id[root],dx1); modify(C0,id[u]+1,-dx1); } LL query(int u,int v) { LL res = 0; while(top[u] != top[v]) { if(d[top[u]] < d[top[v]]) swap(u,v); res += getsum(C2,id[u]) - getsum(C2,id[top[u]]-1); res %= mod; int &son = hson[u]; if(son != 0){ LL x = getsum(C0,id[son]); res += x*x % mod; } LL x = getsum(C0,id[top[u]]); res -= x*x % mod; res %= mod; u = fa[top[u]]; } if(d[u] < d[v]) swap(u,v); res += getsum(C2,id[u]) - getsum(C2,id[v]-1); int &son = hson[u]; if(son != 0){ LL x = getsum(C0,id[son]); res += x*x % mod; } LL x = sum - getsum(C0,id[v]); res += x*x % mod; return (res % mod + mod ) % mod; } void solve() { clr(hson,0); idx = 0;d[root] = 0; fa[root] = root; dfs_sz(root); dfs_chain(root,root); // for(int i = 1; i <= n; i++) // { // printf("%d %d %d %d\n",fa[i],id[i],hson[i],top[i]); // } // cout << "-------" << endl; N = n + 3; clr(C0,0);clr(C2,0); sum = 0; for(int i = 1; i <= n; i++) { int x = w[i]; w[i] = 0; change(i,x); } // for(int i = 1; i <= n; i++) // { // cout <<getsum(C0,id[i]) << " " ; // } // cout << endl << "----->" <<endl; for(int i = 0; i < m; i++) { int op,u,v; scanf("%d%d%d",&op,&u,&v); if(op == 1){ change(u,v); }else{ LL ans = (sum*sum % mod - query(u,v)) % mod; printf("%I64d\n",(ans + mod) % mod); } } } int main() { // freopen("wcbao.in","r",stdin); // int T; while(cin >> n >> m) { input(); solve(); } return 0; }
2. 十 1001 CRB and Apple
数据结构优化dp转移令i < j,
dp[j][i]=dp[i][j]=1+max{dp[i][k]|k<j,d[k]<=d[j]}
If multiple critical pairs exist, output the pair with largest u. If still ambiguous, output the pair with smallest v.
其中,u < v。
题解分析的好。将[1,n]分为两个集合A,B。A中最大值为N,B中最大值为B,则答案为(B,B+1)。
4 . 十 1008 CRB and Roads
DAG任意两点的可达性判断。乱搞。O(N*M)复杂度,用01表示可达性,用bitset或者int压缩一下简化复杂度。
O(N∗M/32)
。就是说不一定老用乘法,复杂度可以做除法(优化)。
5 . 十 1010 CRB and Substrings
对s每次头部去一个,尾部加一个,动态维护后缀数组?
没见过。
6 . 十 1011 CRB and Tree
给一棵节点带权的树,
f(u,v)
表示路径u到v的所有节点权值异或和。询问
f(u,v)=s
的对数。
f(u,v)=f(u,root)⊗f(root,v)
异或和的优美性质