题目大意:给定一棵树,每个节点有一个颜色,多次询问某条路径上颜色数量,强制在线
正解是块状数组,强制在线莫队会TLE到死,想AC这道题的不用看了
如果朴素的跑树上莫队其实并不难- - 但是强制在线
因此我们可以考虑强制在线莫队算法
将树分成O(n^1/3)块,每块大小O(n^2/3)
记录每两块之间的答案、每种颜色的出现次数和哪些点被记录到了答案中
每次查询先找到两端点所在块的端点的答案,然后暴力用莫队转移即可
空间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3)
预处理时间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3)
单次询问时间复杂度O(n^2/3)
然后。。。被卡常数。。。明明本机只要不到11秒就能全部出解。。。BZ渣评测机怎么这么慢。。。
读入优化。。。寻址优化。。。short压内存。。。内嵌汇编强制inline。。。函数改成宏。。。倍增LCA改成RMQLCA。。。三分法修改块的大小。。。还有啥。。。bool改成bitset。。。随机数选根防卡。。。还特意去切了王室联邦练习树分块。。。最后还在结尾附加一段注释增强一下信仰。。。
从早上卡到现在。。。 加上昨天写的版本一共挂了七篇。。。整整七篇。。。。。。。。。。。。。。。。。。。。。
发个本地评测的图吧。。。 此题精神AC了。。。
我が生涯に、一片の悔いなし。。。。。
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 40002
#define B 95
#define Change(x,f,v,ans) { \
if(v[x]) \
{ \
if(!--f[a[x]]) \
--ans; \
v[x]=0; \
} \
else \
{ \
if(!f[a[x]]++) \
++ans; \
v[x]=1; \
} \
}
#define swap(x,y) {int t=x;x=y;y=t;}
using namespace std;
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot;
int n,m,b,cnt,last_ans;
int a