小 Trick 合集
A:区间 [l1,r1] -> [l2,r2] 连有权边跑 dij 优化建图能不能优化?
Q:能。直接优化建图+普通堆是O(nlog^2n)的,实际上可以隐式建图,线段树+vector即可。可以做到 O(nlogn)
代码超级小清新!!
点击查看代码
array<int,3> v[MAX];
vector<int> e[MAX<<2];
bool vis[MAX];
int mn[MAX<<2],sz[MAX<<2],tag[MAX<<2];
void pushdown(int rt){
if(sz[ls(rt)]){
mn[ls(rt)] = min(mn[ls(rt)],tag[rt]);
tag[ls(rt)] = min(tag[ls(rt)],tag[rt]);
}
if(sz[rs(rt)]){
mn[rs(rt)] = min(mn[rs(rt)],tag[rt]);
tag[rs(rt)] = min(tag[rs(rt)],tag[rt]);
}
tag[rt] = inf;
return ;
}
void pushup(int rt){
sz[rt] = sz[ls(rt)]+sz[rs(rt)];
mn[rt] = min(mn[ls(rt)],mn[rs(rt)]);
return ;
}
void build(int lp,int rp,int rt){
if(lp==1)mn[rt]=0;
else mn[rt] = inf;
tag[rt] = inf;
sz[rt] = rp-lp+1;
if(lp>=rp)return ;
int mid = (lp+rp)>>1;
build(lp,mid,ls(rt));
build(mid+1,rp,rs(rt));
return ;
}
void add(int lp,int rp,int l,int r,int idx,int rt){
if(l<=lp&&rp<=r){
e[rt].pb(idx);
return ;
}
int mid = (lp+rp)>>1;
if(l<=mid)add(lp,mid,l,r,idx,ls(rt));
if(r>mid)add(mid+1,rp,l,r,idx,rs(rt));
return ;
}
void chkmin(int lp,int rp,int l,int r,int val,int rt){
if(!sz[rt])return ;
if(l<=lp&&rp<=r){
mn[rt] = min(mn[rt],val);
tag[rt] = min(tag[rt],val);
return ;
}
int mid = (lp+rp)>>1;
pushdown(rt);
if(l<=mid)chkmin(lp,mid,l,r,val,ls(rt));
if(r>mid)chkmin(mid+1,rp,l,r,val,rs(rt));
pushup(rt);
return ;
}
void upd(int lp,int rp,int rt){
for(auto idx:e[rt]){
if(!vis[idx]){
vis[idx] = 1;
chkmin(1,n,v[idx][0],v[idx][1],v[idx][2]+val);
}
}
e[rt].clear();
if(lp>=rp){
sz[rt] = 0;
mn[rt] = inf;
return ;
}
pushdown(rt);
int mid = (lp+rp)>>1;
if(mn[ls(rt)]==mn[rt])upd(lp,mid,val,ls(rt));
else upd(mid+1,rp,val,rs(rt));
pushup(rt);
return ;
}
2、线段树分治相关
线段树分治和cdq分治有的时候不太一样,两者各有侧重,在某些问题上用正确的方法就会让你的思路清晰,代码自然。
https://www.luogu.com.cn/problem/P5244
决策单调性后使用线段树分治去除区间lim的影响,非常牛。
实际上线段树分治严格包含CDQ分治,如果是半在线问题可以看做是 lim = [1,i-1] 然后上线段树分治。
3、线段树trick
如果一个东西离散化比较麻烦,不妨直接上线段树,让线段树帮你找到正确的区间。
4、处理图的利器
在图问题中,看待问题的视角很重要。常见利器有:
dfs树,dfs序,欧拉序,拓扑序。
一些重要性质:
二分图性质,DAG性质等。
5、补集的妙用
一个集合的 mex 可以看做和自然数集的补集中的最小值。
6、修改和查询的对偶
如果区间修+单点查很难写,可以选择改为单点修+区间查
7、模意义下多项式可以做特殊的因式分解。
8、对于一类DS问题。
我们可以把询问用DS维护,然后让操作改他们,非常具有启发性的做法!
https://www.luogu.com.cn/problem/P5576
https://codeforces.com/gym/103260/problem/H
9、对于线段树
在问题的任何步骤,我们都应该思考能否使用线段树直接维护。
https://www.luogu.com.cn/problem/P6780
10、对于更新区间包含的问题,可以用维护mx的seg代替nlogn时间的seg