【WC2013】糖果公园(树上带修莫队)
作者:互联网
Link:
Luogu https://www.luogu.com.cn/problem/P4074
Solution
言い たい ことが あるん だよ!
今天!
我!
把 m 和 q
写着写着
当成一个东西了!!
或许哪一天我又看不懂了我稍微写一写
莫队挂一条欧拉序就可以上树
需要特殊处理一下 LCA
带修就正常地加一条时间轴就可以了
结构体可能开得比较厉害之类的反正写得有点过重
最优解2s 这份代码12s
/kk
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
char frBB[1<<12], *frS=frBB, *frT=frBB;
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
double _db_read()
{
int w = 0; char ch = 0; double x = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
if (ch == '.')
{
double y = 1.0; ch = getchar();
while (isdigit(ch)) x += (y /= 10) * (ch ^ 48), ch = getchar();
}
return w ? -x : x;
}
int _n_read()
{
int w = 0; char ch = 0; int x = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
#define read(x) x=_n_read()
const int MAXM = 2e5 + 10;
const int MAXN = 1e5 + 10;
const int MAXDFN = 3e5 + 10;
int n, m, q;
int v[MAXN];
int w[MAXN];
int tot = 0;
int head[MAXN], nxt[MAXM], to[MAXM];
#define add_edge(u,v) nxt[++tot]=head[u],head[u]=tot,to[tot]=v
int W[MAXN], V[MAXN], C[MAXN];
int depth[MAXN];
int lst[MAXM], in[MAXN], out[MAXN];
int fa[20][MAXN];
int _temp_C[MAXN];
int m_tar[MAXN];
int m_res[MAXN];
int m_prev[MAXN];
int m_tot = 0;
int Bucket[MAXN];
bool vis[MAXN];
int _temp_M = 0;
void DFS(int pos)
{
lst[++lst[0]] = pos;
in[pos] = lst[0];
for (int i = head[pos]; i; i = nxt[i])
{
if (to[i] == fa[0][pos]) continue;
fa[0][to[i]] = pos;
depth[to[i]] = depth[pos] + 1;
DFS(to[i]);
}
lst[++lst[0]] = pos;
out[pos] = lst[0];
}
int lca(const int &tx, const int &ty)
{
if (tx == ty) return tx;
static int x, y;
x = tx;
y = ty;
if (depth[x] < depth[y]) swap(x, y);
for (int i = 17; i >= 0; --i)
{
if (depth[fa[i][x]] >= depth[y])
{
x = fa[i][x];
}
}
if (x == y) return x;
for (int i = 17; i >= 0; --i)
{
if (fa[i][x] != fa[i][y])
{
x = fa[i][x];
y = fa[i][y];
}
}
return fa[0][x];
}
int belong[MAXDFN];
int block_siz, block_cnt;
struct s_q
{
int id, x, y, t, xyLCA, u, v;
s_q() : id(0), x(0), y(0), t(0), xyLCA(0), u(0), v(0) {}
} sq[MAXN];
const bool cmp (const s_q &a, const s_q &b)
{
if (belong[a.x] != belong[b.x])
{
return belong[a.x] < belong[b.x];
}
if (belong[a.y] != belong[b.y])
{
return (belong[a.x] & 1) ? (belong[a.y] < belong[b.y]) : (belong[a.y] > belong[b.y]);
}
return (belong[a.y] & 1) ? (a.t < b.t) : (a.t > b.t);
}
long long _ans_Temp = 0;
long long Ans[MAXN];
void solve(const int &x)
{
if (vis[x] ^= 1)
{
++Bucket[C[x]];
_ans_Temp += 1ll * V[C[x]] * W[Bucket[C[x]]];
return;
}
//else
_ans_Temp -= 1ll * V[C[x]] * W[Bucket[C[x]]];
--Bucket[C[x]];
}
int main()
{
read(n), read(m), read(q);
for (int i = 1; i <= m; ++i)
{
read(V[i]);
}
for (int i = 1; i <= n; ++i)
{
read(W[i]);
}
for (int u, v, i = 1; i < n; ++i)
{
read(u), read(v);
add_edge(u, v);
add_edge(v, u);
}
depth[1] = 1;
DFS(1);
for (int i = 1; i <= 17; ++i)
{
for (int j = 1; j <= n; ++j)
{
fa[i][j] = fa[i-1][fa[i-1][j]];
}
}
for (int i = 1; i <= n; ++i)
{
read(C[i]);
_temp_C[i] = C[i];
}
for (int Type, l, x, y, tx, ty, i = 1; i <= q; ++i)
{
read(Type);
read(x);
read(y);
if (Type) // Type == 1 & Query
{
l = lca(x, y);
if (in[x] > in[y]) swap(x, y);
if (l == x || l == y)
{
tx = in[x], ty = in[y];
}
else
{
tx = out[x], ty = in[y];
}
++_temp_M;
sq[_temp_M].xyLCA = l;
sq[_temp_M].id = _temp_M;
sq[_temp_M].x = tx;
sq[_temp_M].y = ty;
sq[_temp_M].t = m_tot;
sq[_temp_M].u = x;
sq[_temp_M].v = y;
continue;
}
// (Type == 0) & Modify
++m_tot;
m_tar[m_tot] = x;
m_res[m_tot] = y;
m_prev[m_tot] = _temp_C[m_tar[m_tot]];
_temp_C[x] = y;
}
q = _temp_M;
block_siz = pow(lst[0], 0.66667);
for (int block_id = 1, block_pos = 0, i = 1; i <= lst[0]; ++i)
{
++block_pos;
if (block_pos == block_siz + 1)
{
block_pos = 1;
++block_id;
}
belong[i] = block_id;
}
block_cnt = belong[lst[0]];
sort(sq + 1, sq + 1 + q, cmp);
int l = 1, r = 0, t = 0;
for (int i = 1; i <= q; ++i)
{
while (t < sq[i].t)
{
++t;
if (vis[m_tar[t]])
{
_ans_Temp -= 1ll * V[C[m_tar[t]]] * W[Bucket[C[m_tar[t]]]];
--Bucket[C[m_tar[t]]];
++Bucket[m_res[t]];
_ans_Temp += 1ll * V[m_res[t]] * W[Bucket[m_res[t]]];
}
C[m_tar[t]] = m_res[t];
}
while (t > sq[i].t)
{
if (vis[m_tar[t]])
{
_ans_Temp -= 1ll * V[C[m_tar[t]]] * W[Bucket[C[m_tar[t]]]];
--Bucket[C[m_tar[t]]];
++Bucket[m_prev[t]];
_ans_Temp += 1ll * V[m_prev[t]] * W[Bucket[m_prev[t]]];
}
C[m_tar[t]] = m_prev[t];
--t;
}
while (l < sq[i].x)
{
solve(lst[l]);
++l;
}
while (l > sq[i].x)
{
--l;
solve(lst[l]);
}
while (r < sq[i].y)
{
++r;
solve(lst[r]);
}
while (r > sq[i].y)
{
solve(lst[r]);
--r;
}
// for (int i = 1; i <= n; ++i)
// cout << '<' << i << ' ' << vis[i] << ">\n";
// cout << "FAQ" << i << "FAQ\n";
if (sq[i].u != sq[i].xyLCA && sq[i].v != sq[i].xyLCA)
{
solve(sq[i].xyLCA);
Ans[sq[i].id] = _ans_Temp;
solve(sq[i].xyLCA);
continue;
}
Ans[sq[i].id] = _ans_Temp;
}
for (int i = 1; i <= q; ++i)
{
printf("%lld\n", Ans[i]);
}
return 0;
}
标签:temp,int,sq,belong,Bucket,WC2013,include,糖果,修莫队 来源: https://www.cnblogs.com/ccryolitecc/p/13993761.html