数据结构
树状数组:
template<typename T>
struct BIT{
T a[N];
int size = N;
void init(int s){
size = s;
for(int i = 0; i <= s; i++){
a[i] = 0;
}
}
T query(int x){
assert(x <= size);
T s = 0;
for(; x; x -= x&(-x)){
s += a[x];
}
return s;
}
void modify(int x,T s){
assert(x != 0);
for(; x <= N; x += x&(-x)){
a[x] += s;
}
}
};
BIT<int> bit;
线段树(单点修改最小值)
template<typename T>
struct SegmentTree{
T a[N];
struct node{
T va;
}seg[4 * N];
void init(int v = 0){
for(int i = 0; i < N; i++) a[i] = v;
}
void update(int id){
seg[id].va = min(seg[id*2].va, seg[id*2+1].va);
}
void build(int id, int l, int r){
if (l == r) {
seg[id].va = a[l];
} else {
int mid = (l + r) / 2;
build(id*2, l, mid);
build(id*2+1, mid + 1, r);
update(id);
}
}
void change (int id, int l, int r, int pos, T val) {
if (l == r) {
seg[id].va = val;
} else {
int mid = (l + r) / 2;
if(pos <= mid) change(id * 2, l, mid, pos, val);
else change(id * 2 + 1, mid + 1, r, pos, val);
update(id);
}
}
T query(int id, int l, int r, int ql, int qr){
if(l==ql && r == qr) return seg[id].va;
int mid = (l + r) / 2;
if(qr <= mid) return query(id * 2, l ,mid, ql, qr);
else if(ql > mid){return query(id * 2 + 1, mid + 1, r, ql, qr);}
else{
return min(query(id * 2, l ,mid, ql, mid), query(id * 2 + 1, mid + 1, r, mid+1, qr));
}
}
};
SegmentTree<ll> Seg;
线段树(区间修改区间和)
template<typename T>
struct SegmentTree{
T a[N];
void init(int v = 0) {for(int i = 0; i < N; i++) a[i] = v;}
struct tag{T mul, add; };
struct node{
tag t; T val;
int sz;
}seg[4*N];
friend tag operator+ (const tag &t1, const tag &t2) {
return {t1.mul * t2.mul % mod , (t1.add * t2.mul + t2.add)%mod};
}
void update(int id) {
seg[id].val = (seg[id * 2].val + seg[id * 2 + 1].val) % mod;
}
void settag(int id, tag t) {
seg[id].t = seg[id].t + t;
seg[id].val = (seg[id].val * t.mul + seg[id].sz * t.add) % mod;
}
void pushdown(int id) {
if(seg[id].t.mul!=1||seg[id].t.add!=0){
settag(id*2, seg[id].t);
settag(id*2+1, seg[id].t);
seg[id].t.mul = 1;
seg[id].t.add = 0;
}
}
void build(int id, int l, int r) {
seg[id].t = {1,0}; seg[id].sz = r - l + 1;
if (l == r) {
seg[id].val = {a[l]};
} else {
int mid = (l + r) / 2;
build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r);
update(id);
}
}
void modify(int id, int l, int r, int ql, int qr, tag t) {
if (l == ql && r == qr) {
settag(id, t);
return;
}
int mid = (l + r) / 2;
pushdown(id);
if (qr <= mid) modify(id * 2, l, mid, ql, qr, t);
else if (ql > mid) modify(id * 2+1, mid + 1, r, ql, qr, t);
else{
modify(id * 2, l, mid, ql, mid, t);
modify(id * 2 + 1, mid + 1, r, mid + 1, qr ,t);
}
update(id);
}
void change(int id, int l, int r, int pos, T val) {
if (l == r) {
seg[id].val = {val};
}else{
int mid = (l + r) / 2;
if(pos <= mid) change(id * 2, l, mid, pos, val);
else change(id * 2 + 1, mid + 1, r, pos, val);
update(id);
}
}
T query(int id, int l, int r, int ql, int qr){
if (l==ql && r == qr) return seg[id].val;
int mid = (l + r) / 2;
pushdown(id);
if (qr <= mid) return query(id * 2, l ,mid, ql, qr);
else if (ql > mid) return query(id * 2 + 1, mid + 1, r, ql, qr);
else return (query(id * 2, l ,mid, ql,mid) + query(id * 2 + 1, mid + 1, r, mid+1, qr))%mod;
}
};
SegmentTree<ll> Seg;
线段树上二分
int search(int id,int l,int r,int ql,int qr,int x){
if(l==ql&&r==qr){
if(seg[id].val<x) return -1;
else{
if(l==r) return l;
int mid=(l+r)/2;
if(seg[id*2].val>=x) return search(id*2,l,mid,ql,mid,x);
else return search(id*2+1,mid+1,r,mid+1,qr,x);
}
}
int mid = (l+r)/2;
if(qr<=mid) return search(id*2,l,mid,ql,qr,x);
else if(ql>mid) return search(id*2+1,mid+1,r,ql,qr,x);
else{
int pos = search(id*2,l,mid,ql,mid,x);
if(pos==-1) return search(id*2+1,mid+1,r,mid+1,qr,x);
else return pos;
}
}//not sort
莫队
int q,res;array<int,3>que[N];
void add(int x){}
void del(int x){}
int calc(){ return res;}
vector<int> Mo(){
res=0;int B=500;//sqrt(Q)
vector<int> ans(q+1);
sort(que+1,que+q+1,[&](array<int,3> a,array<int,3> b){
int c=a[0]/B;
if(c!=b[0]/B) return c<b[0]/B;
return c%2?a[1]>b[1]:a[1]<b[1];
});
int l=1,r=0;
for(int i=1;i<=q;i++){
while(r<que[i][1]) r++,add(r);
while(l>que[i][0]) l--,add(l);
while(r>que[i][1]) del(r),r--;
while(l<que[i][0]) del(l),l++;
ans[que[i][2]]=calc();
}
while(l<=r) del(l++);
return ans;
}
并查集
struct DSU {
vector<int> f, siz;
DSU() {}
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
std::iota(f.begin(), f.end(), 0);
siz.assign(n, 1);
}
int find(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
bool same(int x, int y) {
return find(x) == find(y);
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
}
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) {
return siz[find(x)];
}
};
LCA(倍增)
int n, m;
vector<int> e[N];
int root, fa[N][21], dep[N];
bool vis1[N];
void dfs(int x) {
vis1[x] = 1;
for (auto y : e[x]) if (!vis1[y]) {
fa[y][0] = x;
dep[y] = dep[x] + 1;
dfs(y);
}
}
void LCA_init(int x){
root = x;
memset(dep, 0, sizeof dep);
dfs(root);
for(int i = 1; i <= 20; i++){
for(int j = 1; j <= n; j++){
if(fa[j][i - 1]) {
fa[j][i] = fa[fa[j][i - 1]][i - 1];
}
}
}
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
int z = dep[x] - dep[y];
for(int j = 0; j <= 20 && z; j++, z/=2) {
if(z & 1) x = fa[x][j];
}
if(x == y) return x;
for(int j = 20; j >= 0; j--){
if(fa[x][j] != fa[y][j]){
x = fa[x][j], y = fa[y][j];
}
}
return fa[x][0];
}
LCA(树链剖分)
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 101000;
//O(n) - O(lgn)
int n;
std::vector<int> e[N];
int l[N], r[N], id[N];
int sz[N], hs[N], tot, top[N], dep[N], fa[N];
void dfs1(int u, int f){
sz[u] = 1;
hs[u] = -1;
fa[u] = f;
dep[u] = dep[f] + 1;
for(auto v : e[u]){
if(v == f) continue;
dfs1(v, u);
sz[u] += sz[u];
if(hs[u] == -1 || sz[v] > sz[hs[u]]){
hs[u] = v;
}
}
}
void dfs2(int u, int t){
top[u] = t;
l[u] = ++tot;
id[tot] = u;
if(hs[u] != -1){
dfs2(hs[u], t);
}
for(auto v : e[u]) {
if(v != fa[u] && v != hs[u]) {
dfs2(v, v);
}
}
r[u] = tot;
}
int LCA(int u, int v){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) v=fa[top[v]];
else u = fa[top[u]];
}
if(dep[u] < dep[v]) return u;
else return v;
}
void work(){
dfs1(1,0);dfs2(1,1)
}
int main() {
cin>>n;
for(int i = 1; i <= n; i++){
int u, v; cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
work();
int a, b; cin >> a >> b;
cout << LCA(a, b);
}
树链剖分(重链)
struct HLD{
int n,tot;
std::vector<std::vector<int>> e;
std::vector<int> l, r, id;
std::vector<int> sz, hs, top, dep, fa;
HLD() {}
HLD(int n) {
init(n);
}
void init(int n) {
this->n = n;n++;
sz.resize(n);
hs.resize(n);
top.resize(n);
dep.resize(n);
fa.resize(n);
l.resize(n);
r.resize(n);
id.resize(n);
tot = 0;
e.assign(n, {});
}
void addEdge(int u, int v){
e[u].push_back(v);
e[v].push_back(u);
}
void work(int root = 1){
top[root] = root;
dep[root] = 0;
fa[root] = -1;
dfs1(root,0);
dfs2(root,root);
}
void dfs1(int u, int f){
sz[u] = 1;
hs[u] = -1;
fa[u] = f;
dep[u] = dep[f] + 1;
for(auto v : e[u]){
if(v == f) continue;
dfs1(v, u);
sz[u] += sz[v];
if(hs[u] == -1 || sz[v] > sz[hs[u]]){
hs[u] = v;
}
}
}
void dfs2(int u, int t){
top[u] = t;
l[u] = ++tot;
id[tot] = u;
if(hs[u] != -1){
dfs2(hs[u], t);
}
for(auto v : e[u]) {
if(v != fa[u] && v != hs[u]) {
dfs2(v, v);
}
}
r[u] = tot;
}
int LCA(int u, int v){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) v=fa[top[v]];
else u = fa[top[u]];
}
if(dep[u] < dep[v]) return u;
else return v;
}
int dist(int u, int v){
return dep[u] + dep[v] - 2 * dep[LCA(u, v)];
}
int jump(int u, int k){
if(dep[u] < k) {
return -1;
}
int d = dep[u] - k;
while(dep[top[u]] > d){
u = fa[top[u]];
}
return id[l[u] - dep[u] + d];
}
bool isAncester(int u, int v) {
return l[u] <= l[v] && l[v] < r[u];
}
int rootedChild(int u, int v) {
if (u == v) {
return u;
}
if (!isAncester(u, v)) {
return fa[u];
}
auto it = std::upper_bound(e[u].begin(), e[u].end(), v, [&](int x, int y) {
return l[x] < l[y];
}) - 1;
return *it;
}
int rootedSize(int u, int v) {
if (u == v) {
return n;
}
if (!isAncester(v, u)) {
return sz[v];
}
return n - sz[rootedChild(v, u)];
}
int rootedLca(int a, int b, int c) {
return LCA(a, b) ^ LCA(b, c) ^ LCA(c, a);
}
};
树上启发式合并
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
vector<int>e[N];
int l[N],r[N],id[N],sz[N],hs[N],tot;
void dfs_init(int u,int f){
l[u]=++tot;
id[tot]=u;
sz[u]=1;
hs[u]=-1;
for(auto v : e[u]){
if(f==v) continue;
dfs_init(v,u);
sz[u]+=sz[v];
if(hs[u]==-1||sz[v]>sz[hs[u]]){
hs[u]=v;
}
}
r[u]=tot;
}
void dfs_solve(int u,int f,bool keep){
for(auto v:e[u]){
if(v!=f&&v!=hs[u]){
dfs_solve(v,u,false);
}
}
if(hs[u]!=-1){
dfs_solve(hs[u],u,true);
}
for(auto v:e[u]){
if(v!=f&&v!=hs[u]){
for(int x=l[v];x<=r[v];x++){
add(id[x]);
}
}
}
add(u);
if(!keep){//清空
for(int x=l[u];x<=r[u];x++){
del(id[x]);
}
}
}
int main(){
return 0;
}
ST表
/*
预处理区间
把一段区间分成两个2的幂次区间的覆盖,用于与自己做运算不变的运算如gcd,max,min,^等\
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010000,LOGN=20;
int n,q,lg[N];
int A,B,C,l,r,a[N],f[N][22];
void init_ST(){
for(int j=1;j<=LOGN;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
lg[1]=0;
for(int i=2;i<=n;i++) lg[i]=lg[i/2]+1;//预处理x取log下取整
}
int main(){
scanf("%d%d%u%u%u",&n,&q,&A,&B,&C);
int ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
f[i][0]=a[i];
}
for(int i=1;i<=q;i++){
scanf("%u%u",&l,&r);
int len=lg[r-l+1];
ans^=max(f[l][len],f[r-(1<<len)+1][len]);
}
return 0;
}

浙公网安备 33010602011771号