数据结构模板
堆
struct Heap{
priority_queue<ll>q1,q2;
inline void push(ll x){q1.push(x);}
inline void erase(ll x){q2.push(x);}
inline void updata(){while(!q1.empty()&&!q2.empty()&&q1.top()==q2.top())q1.pop(),q2.pop();}
inline ll top(){updata();return q1.top();}
}Q;ST表
静态求区间最大值,基于倍增的思想
int N,M;
int arr[maxn],Log2[maxn];//原始数组,log2(x)数组
int f[maxn][20];//F[i][j]: arr[i~i+2^j-1]的最大值
void ST_init(){ //初始化所有长度为2^x的区间最大值
for(int i = 1;i<=N;i++) Log2[i] = log(i)/log(2); //初始化log求值,之后O(1)取值
for(int i = 1;i<=N;i++) f[i][0] = arr[i];
int len = log(N)/log(2) +1;
for(int j = 1;j<len;j++){
for(int i = 1;i<=N-(1<<j)+1;i++){
f[i][j] = max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){ //查询arr[l~r]区间的最值
int k = Log2[r-l+1];
return max(f[l][k],f[r-(1<<k)+1][k]);
}并查集
int find(int x){
return fa[x] == x? x: fa[x] = find(fa[x]);
}
void join(int x,int y){
int fx = find(x),fy = find(y);
if(fx != fy) fa[fx] = fy;
}
for(int i = 1;i<=N;i++) fa[i] = i;//一定要初始化分块
以求和为例
ll arr[maxn],base[maxn],res[maxn],B;//B:块的大小
void init(){ //分块初始化:每一个块维护[id*B,(id+1)*B],id是块的编号
for(int i = 1;i<=N;i++) res[i/B] += arr[i];
}
void modify(int l,int r,int v){ //sqrt(N)修改复杂度
int bl = l/B,br = r/B;
ll ans = 0;
if(bl == br){
for(int i = l;i<=r;i++) arr[i] += v,res[bl] += v;
}else{
for(int i = l;i<(bl+1)*B;i++) arr[i]+=v,res[bl] += v;//小块
for(int i = bl+1;i<=br-1;i++) base[i]+=v,res[i] += (ll)v*B;//大块
for(int i = br*B;i<=r;i++) arr[i] +=v,res[br] += v;//小块
}
}
ll query(int l,int r){//sqrt(N)查询复杂度
int bl = l/B, br = r/B;
ll ans = 0;
if(bl == br){
for(int i = l;i<=r;i++) ans += arr[i] + base[bl];
}else{
for(int i = l;i<(bl+1)*B;i++) ans += arr[i] + base[bl];
for(int i = bl+1;i<=br-1;i++) ans += res[i];
for(int i = br*B;i<=r;i++) ans += arr[i] + base[br];
}
return ans;
}奇奇怪挂的数据结构
马拉车算法
string s;
int ans[maxn],str[maxn],lef[maxn];
//ans:每一点的回文半径,str:插#字符后的字符串 lef:以某个为左边界的最长回文子串长度
int build(const string &s){
int n = s.length(), m = (n + 1)*2, ret = 0;
str[0] = '$'; str[m] = '@'; str[1] = '#'; ans[1] = 1;
for (int i = 1; i <= n; i++)
str[i*2] = s[i - 1], str[i*2+1] = '#';
ans[1] = 1;
for (int r = 0, p = 0, i = 2; i < m; ++i){
if (r > i) ans[i] = min(r - i, ans[p * 2 - i]);
else ans[i] = 1;
while(str[i - ans[i]] == str[i + ans[i]]) ++ans[i];
if (i + ans[i] > r) r = i + ans[i], p = i;
ret = max(ret, ans[i] - 1);
}
// 计算维护以每个位置为起点的最长回文串
for (int i = 0; i <= m; i++) lef[i] = 0;
for (int i = 2; i < m; i++) if (lef[i - ans[i] + 1] < i + 1) lef[i - ans[i] + 1] = i + 1;
for (int i = 1; i <= m; i++) if (lef[i] < lef[i - 1]) lef[i] = lef[i - 1];
return ret;//最长回文串的长度
}
int mid(int x, bool odd){
//求以x为中心的最长回文子串长度,若是求偶回文串,这里中心认为是中间靠左
if (odd) return ans[(x + 1) << 1] - 1;
return ans[(x + 1) << 1 | 1] - 1;
}
int left(int x){
//求以x为左端点的最长回文串的长度
return lef[(x + 1) << 1] - ((x+1) << 1);
}树状数组
二维树状数组 [单点修改、区间查询]
int N,M;//N*M的矩阵
int tr[1111][1111];
int lowbit(int x){
return x&-x;
}
void add(int x,int y,int v){
for(int i = x;i<=N;i += lowbit(i)){
for(int j = y;j<=M;j += lowbit(j)){
tr[i][j] += v;
}
}
}
ll pre_sum(int x,int y){ //查询(1,1)到(x,y)矩阵和
ll sum = 0;
for(int i = x;i>=1;i -= lowbit(i)){
for(int j = y;j>=1;j -= lowbit(j)){
sum += tr[i][j];
}
}
return sum;
}
ll query(int x1,int y1,int x2,int y2){ //查询(x1,y2)到(x2,y2)的矩阵和
return pre_sum(x2,y2) - pre_sum(x1-1,y2) - pre_sum(x2,y1-1) + pre_sum(x1-1,y1-1);
}二维树状数组 [区间修改,单点查询]
int tr[1010][1010];//NxN的矩阵
int lowbit(int x){
return x&-x;
}
void add(int x,int y,int v){
for(int i = x;i<=N;i += lowbit(i))
for(int j = y;j<=N;j += lowbit(j))
tr[i][j] += v;
}
int query(int x,int y){
int sum = 0;
for(int i = x;i>=1;i -= lowbit(i))
for(int j = y;j>=1;j -= lowbit(j))
sum += tr[i][j];
return sum;
}
//给左上角(x1,y1) ,右下角(x2,y2)的矩阵+v
add(x1,y1,+v);
add(x1,y2+1,-v);
add(x2+1,y1,-v);
add(x2+1,y2+1,+v);Ryuichi的算法分享 文章被收录于专栏
分享我的一些算法题解,致力于把题解做好,部分题解可能会采用视频的形式来讲解。
