A 判断完是决策单调性之后决定回来写(埋下伏笔),B 的题面不好看直接跳了,发现 C 是小清新数据结构,一个小时内会了,又断断续续写了三个小时,最后剩 20min 急忙码完 A 的暴力。
60+0+90 鉴定为菜就多练。
A.共享单车
决策单调性板题,\(O(n^2k)\) 暴力,打个表,发现决策单调性,套上来就行了。
B.困难重重
网络流板题,好像比 A 还简单,还好我直接跳了。
首先网格图黑白染色,如果 \(A=B\) 和源点或汇点连费用递增的四条边,直接费用流,\(A\neq B\) 就拆点,额外拆出横点和纵点两个点,横连横,纵连纵,第二条边费用为 \(B-A\) 。
C.简单树题
赛时冲这题,这辈子有了。
你都分块套树了空间还开 \(512MB\) 卡掉我 \(10\) 分,非得把线段树换成树状数组是吧,还好我有 \(\text{short}\) 。
[LNOI2014] LCA 带边权,带修,强制在线。
题面
给出一棵 \(n\) 个点的树,给出树上每条边的长度。
你需要顺次执行 \(m\) 个操作,操作分为两种:
- \(1\ x\ y\):将树上的第 \(x\) 条边的长度修改成 \(y\)。
- \(2\ l\ r\ x\):对于当前这棵树,查询编号在 \([l,r]\) 内的所有点到点 \(x\) 的距离之和。
首先选定根,求出每个点到根距离,记为 \(dis_x\)
\(\sum\limits_{i=l}^{r}dis(x,i)=dis_x\times(r-l+1)+\sum\limits_{i=l}^{r}dis_i-2\sum\limits_{i=l}^{r}dis_{LCA(x,i)}\) 。
分为两部分维护,一部分要维护 \(\sum\limits_{i=l}^{r}dis_i\),每次修改一条边就是对 \(dfn_i\in[dfn_x,dfn_x+siz_x-1]\) 的点进行修改,分块套树状数组解决。另一部分要维护 \(\sum\limits_{i=l}^{r}dis_{LCA(x,i)}\) ,首先求这东西用 [LNOI2014] LCA 中的 Trick,然后分块套线段树维护 \([l,r]\) 进行到根路径加后的线段树,询问时这两部分一拼就好了。
点击查看代码
#include <bits/stdc++.h>
#define fr first
#define se second
#define U unsigned
#define LL long long
#define pb push_back
#define pii pair<int,int>
#define pLi pair<LL,int>
#define pLL pair<LL,LL>
#define __ __int128
#define ld long double
#define VE vector<LL>
#define db double
using namespace std;
inline int read()
{
int x = 0,f = 1;char ch = getchar();
while(!isdigit(ch)) (ch == '-') && (f = -1),ch = getchar();
while(isdigit(ch)) x = x*10+ch-48,ch = getchar();
return x*f;
}
inline char R()
{
char ch = getchar();
while (!islower(ch)) ch = getchar();
return ch;
}
const int N = 6e4+5,S = 250;
struct Edge{int u,v,w;}E[N];
struct edge{int to,w,pre;}e[N<<1];
int las[N],cnt,dfn[N],top[N],siz[N],dep[N],fa[N],hs[N],d,to[N];
LL dis[N],val[N];
inline void add(int u,int v,int w){e[++cnt] = {v,w,las[u]},las[u] = cnt;}
void D1(int x)
{
dep[x] = dep[fa[x]]+1,siz[x] = 1;
for (int i = las[x],y;i;i = e[i].pre)
{
if ((y = e[i].to) != fa[x])
{
dis[y] = dis[x]+e[i].w,fa[y] = x,D1(y),siz[x] += siz[y];
if (siz[y] > siz[hs[x]]) hs[x] = y;
}
}
}
void D2(int x,int t)
{
dfn[x] = ++d,top[x] = t;
if (hs[x]) D2(hs[x],t);
for (int i = las[x],y;i;i = e[i].pre)
if ((y = e[i].to) != fa[x] && y != hs[x]) D2(y,y);
}
inline int LCA(int x,int y)
{
while (top[x] != top[y])
dep[top[x]] < dep[top[y]] ? y = fa[top[y]] : x = fa[top[x]];
return dep[x] < dep[y] ? x : y;
}
int bl[N],pos[N],B,n,l1[S],r1[S],rt[S],ls[N*390],rs[N*390],ct;
short laz[N*390],t[N*390];
LL sum[S],s[N*390],c[N];
struct vec
{
int a[S],siz;LL laz[S];
void push_back(int x){a[++siz] = x;}
void A(int i,LL k){while (i <= siz) laz[i] += k,i += i&-i;}
LL Q(int i){LL res = 0;while(i) res += laz[i],i -= i&-i;return res;}
}ve[S];
void A(int i,LL k){while(i <= n) c[i] += k,i += i&-i;}
LL Q(int i){LL res = 0;while(i) res += c[i],i -= i&-i;return res;}
void down(int l,int r,int i)
{
int mid = (l+r)>>1;
if (!ls[i]) ls[i] = ++ct;
if (!rs[i]) rs[i] = ++ct;
laz[ls[i]] += laz[i],laz[rs[i]] += laz[i];
t[ls[i]] += laz[i],t[rs[i]] += laz[i];
s[ls[i]] += (Q(mid)-Q(l-1))*laz[i],s[rs[i]] += (Q(r)-Q(mid))*laz[i];
laz[i] = 0;
}
void M1(int l,int r,int L,int R,int &i)
{
if (!i) i = ++ct;
if (l >= L && r <= R)
return (void)(laz[i]++,t[i]++,s[i] += Q(r)-Q(l-1));
if (laz[i]) down(l,r,i);
int mid = (l+r)>>1;
if (L <= mid) M1(l,mid,L,R,ls[i]);
if (mid+1 <= R) M1(mid+1,r,L,R,rs[i]);
s[i] = s[ls[i]]+s[rs[i]];
}
void M2(int l,int r,int p,LL k,int &i)
{
if (!i) i = ++ct;
if (l == r) return (void)(s[i] += k*t[i]);
if (laz[i]) down(l,r,i);
int mid = (l+r)>>1;
if (p <= mid) M2(l,mid,p,k,ls[i]);
else M2(mid+1,r,p,k,rs[i]);
s[i] = s[ls[i]]+s[rs[i]];
}
void M3(int x,int id){while(x)M1(1,n,dfn[top[x]],dfn[x],rt[id]),x = fa[top[x]];}
LL Q1(int l,int r,int L,int R,int i)
{
if (!i) return 0;
if (l >= L && r <= R) return s[i];
if (laz[i]) down(l,r,i);
LL res = 0;int mid = (l+r)>>1;
if (mid >= L) res += Q1(l,mid,L,R,ls[i]);
if (mid+1 <= R) res += Q1(mid+1,r,L,R,rs[i]);
return res;
}
LL Q2(int x,int id)
{
LL res = 0;
while (x) res += Q1(1,n,dfn[top[x]],dfn[x],rt[id]),x = fa[top[x]];
return res;
}
inline void build()
{
for (int i = 1;i <= n;i++)
bl[i] = (i-1)/B+1,ve[bl[i]].pb(dfn[i]),
sum[bl[i]] += dis[i],M3(i,bl[i]);
for (int i = 1;i <= bl[n];i++)
sort(ve[i].a+1,ve[i].a+ve[i].siz+1),l1[i] = (i-1)*B+1,r1[i] = min(i*B,n);
for (int i = 1;i <= bl[n];i++)
for (int j = 1;j <= ve[i].siz;j++)
pos[ve[i].a[j]] = j;
}
inline void M(int l,int r,int x,int y)
{
LL k = y-val[x];
for (int i = 1;i <= bl[n];i++)
{
int L = lower_bound(ve[i].a+1,ve[i].a+ve[i].siz+1,l)-ve[i].a,R = upper_bound(ve[i].a+1,ve[i].a+ve[i].siz+1,r)-ve[i].a;
sum[i] += 1LL*(R-L)*k,ve[i].A(L,k),ve[i].A(R,-k),M2(1,n,dfn[x],k,rt[i]);
}
A(dfn[x],k),val[x] = y;
}
inline LL Q(int l,int r)
{
LL res = 0;
if (bl[l] == bl[r]) for (int i = l;i <= r;i++) res += dis[i]+ve[bl[l]].Q(pos[dfn[i]]);
else
{
for (int i = l;i <= r1[bl[l]];i++) res += dis[i]+ve[bl[l]].Q(pos[dfn[i]]);
for (int i = bl[l]+1;i < bl[r];i++) res += sum[i];
for (int i = l1[bl[r]];i <= r;i++) res += dis[i]+ve[bl[r]].Q(pos[dfn[i]]);
}
return res;
}
LL Q3(int l,int r,int x)
{
LL res = 0;
if (bl[l] == bl[r]) for (int i = l,L;i <= r;i++) L = LCA(i,x),res += Q(L,L);
else
{
for (int i = l,L;i <= r1[bl[l]];i++) L = LCA(i,x),res += Q(L,L);
for (int i = bl[l]+1;i < bl[r];i++) res += Q2(x,i);
for (int i = l1[bl[r]],L;i <= r;i++) L = LCA(i,x),res += Q(L,L);
}
return res;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n = read();int m = read(),typ = read();B = sqrt(n)+1;
for (int i = 1;i < n;i++)
E[i] = {read(),read(),read()},add(E[i].u,E[i].v,E[i].w),add(E[i].v,E[i].u,E[i].w);
D1(1),D2(1,1);
for (int i = 1;i < n;i++)
{
if(dep[E[i].u] < dep[E[i].v]) val[E[i].v] = E[i].w,to[i] = E[i].v;
else val[E[i].u] = E[i].w,to[i] = E[i].u;
}
for (int i = 1;i <= n;i++) A(dfn[i],val[i]);
build();
int las = 0;
while (m--)
{
char op = R();int l = read()^(las*typ),r = read()^(las*typ);
if (op == 'm') M(dfn[to[l]],dfn[to[l]]+siz[to[l]]-1,to[l],r);
else
{
int x = read()^(las*typ);
LL ans = -Q3(l,r,x)*2+Q(x,x)*(r-l+1)+Q(l,r);
las = ans%n;
printf("%lld\n",ans);
}
}
return 0;
}