2018.12.15省选考试
题目
树上求子树内出现次数>=1且在区间【l,r】内的数
题解
这道题的最初版本是询问子树不同颜色个数, 是一道很经典的 “树比序列容易” 的题.
在树上可以这样做: 对于每一种颜色, 将这种颜色的点提取出来按 DFS 序排序; 令每个点的贡
献为 1, 相邻点的 LCA 的贡献为 −1, 于是问题转化为区间求和.
修改颜色用这种做法是很好实现的, 只需对于每个颜色维护一个 set 即可.
询问颜色区间也很简单, 把线段树换成主席树就可以了; 有修改的话, 换成树状数组套线段树就
好了.
时间复杂度 O(nlog 2 n).
自己
显然而又恶心而又绝望
数据在博客文件里面
代码
// Copyright (C) 2017 __debug.
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; version 3
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; If not, see <http://www.gnu.org/licenses/>.
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#define x first
#define y second
#define MP std::make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#ifdef __linux__
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif
using std::pair;
using std::vector;
using std::string;
typedef long long LL;
typedef pair<int, int> Pii;
const int oo = 0x3f3f3f3f;
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, true : false; }
string procStatus()
{
std::ifstream t("/proc/self/status");
return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
}
template<typename T> T read(T &x)
{
int f = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
f = (ch == '-' ? -1 : 1);
for (x = 0; isdigit(ch); ch = getchar())
x = 10 * x + ch - '0';
return x *= f;
}
template<typename T> void write(T x)
{
if (x == 0) {
putchar('0');
return;
}
if (x < 0) {
putchar('-');
x = -x;
}
static char s[20];
int top = 0;
for (; x; x /= 10)
s[++top] = x % 10 + '0';
while (top)
putchar(s[top--]);
}
// EOT
const int MAXN = 1e5 + 5, LOGN = 18;
int N, Q, online;
vector<int> G[MAXN];
int C[MAXN];
void input()
{
read(N); read(Q); read(online);
for (int i = 1; i <= N; ++i) {
read(C[i]);
}
for (int i = 1; i < N; ++i) {
int u, v;
read(u); read(v);
G[u].push_back(v);
G[v].push_back(u);
}
}
std::set<int> S[MAXN];
int dfsclock, dfnL[MAXN], dfnR[MAXN], id[MAXN];
int dep[MAXN], fa[MAXN][LOGN];
//set【颜色】 存下标
//处理括号序
//求lca
void dfs(int u, int f)
{
dfnL[u] = ++dfsclock;
id[dfsclock] = u;
S[C[u]].insert(dfnL[u]);
for (auto v : G[u]) {
if (v == f)
continue;
dep[v] = dep[u] + 1;
fa[v][0] = u;
for (int i = 1; i < LOGN; ++i) {
fa[v][i] = fa[fa[v][i - 1]][i - 1];
}
dfs(v, u);
}
dfnR[u] = dfsclock;
}
int getLCA(int u, int v)
{
if (dep[u] < dep[v])
std::swap(u, v);
for (int i = LOGN - 1; i >= 0; --i) {
if (dep[fa[u][i]] >= dep[v])
u = fa[u][i];
}
if (u == v)
return u;
for (int i = LOGN - 1; i >= 0; --i) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
namespace SEGT
{
const int SIZE = 8e7 + 5;
int size, lc[SIZE], rc[SIZE];
int sum[SIZE];
inline int add(int v, int l, int r, int p, int x)
{
int u = ++size;
if (l == r) {
sum[u] = sum[v] + x;
return u;
}
int mid = (l + r) >> 1;
if (p <= mid) {
lc[u] = add(lc[v], l, mid, p, x);
rc[u] = rc[v];
} else {
lc[u] = lc[v];
rc[u] = add(rc[v], mid + 1, r, p, x);
}
sum[u] = sum[lc[u]] + sum[rc[u]];
return u;
}
inline int getsum(int u, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return sum[u];
int mid = (l + r) >> 1;
return (ql <= mid ? getsum(lc[u], l, mid, ql, qr) : 0) + (mid < qr ? getsum(rc[u], mid + 1, r, ql, qr) : 0);
}
void debug(int now,int l,int r) {
if(l==r) {
std::cout<<sum[now]<<" "<<l<<"\n";
if(l==N) puts("____");
return ;
}
int mid=(l+r)>>1;
debug(lc[now],l,mid);
debug(rc[now],mid+1,r);
}
}
namespace BIT
{
int root[MAXN];
inline void add(int p, int q, int x)
{
for (; p <= N; p += p & -p) {
root[p] = SEGT::add(root[p], 1, N, q, x),std::cout<<p<<" "<<q<<"<\n";
}
}
inline int getsum(int p, int ql, int qr)
{
int ret = 0;
for (; p; p -= p & -p) {
// SEGT::debug(root[p],1,N);
std::cout<<ql<<" "<<qr<<"!\n";
ret += SEGT::getsum(root[p], 1, N, ql, qr);
std::cout<<ret<<">>>??\n";
}
return ret;
}
}
inline void contrib(int u, int v, int f)
{
u = id[u];
v = id[v];
BIT::add(C[u], dfnL[getLCA(u, v)], f);
}
void solve()
{
dep[1] = 1;
dfs(1, 0);
for (int i = 1; i <= N; ++i) {
for (auto it = S[i].begin(); it != S[i].end(); ++it) {
BIT::add(i, *it, +1);
// if (it != S[i].begin())
// contrib(*std::prev(it), *it, -1);//相邻两个之间减去他们的lca
}
}
// for(int i=1;i<=N;++i) SEGT::debug(BIT::root[i],1,N);
// return;
int lastans = 0;
while (Q--) {
int op, u, c, l, r;
read(op); read(u);
u ^= lastans;
if (op == 1) {
read(l); read(r);
l ^= lastans;
r ^= lastans;
lastans = BIT::getsum(r, dfnL[u], dfnR[u]) ;//- BIT::getsum(l - 1, dfnL[u], dfnR[u]);
write(lastans); putchar('\n');
} else if (op == 2) {
read(c);
c ^= lastans;
auto it = S[C[u]].find(dfnL[u]);
bool p = it != S[C[u]].begin();
bool n = std::next(it) != S[C[u]].end();
if (p)
contrib(*std::prev(it), *it, +1);
if (n)
contrib(*it, *std::next(it), +1);
if (p && n)
contrib(*std::prev(it), *std::next(it), -1);
BIT::add(C[u], dfnL[u], -1);
S[C[u]].erase(it);
C[u] = c;
BIT::add(C[u], dfnL[u], +1);
it = S[C[u]].insert(dfnL[u]).x;
p = it != S[C[u]].begin();
n = std::next(it) != S[C[u]].end();
if (p)
contrib(*std::prev(it), *it, -1);
if (n)
contrib(*it, *std::next(it), -1);
if (p && n)
contrib(*std::prev(it), *std::next(it), +1);
}
if (!online)
lastans = 0;
}
}
int main()
{
// freopen("xmastree1.in","r",stdin);
// freopen("xmastree1.out","w",stdout);
input();
solve();
}