可爱的板子们
可爱的板子们
-std=c++14 -O2 -Wshadow -Wall -Wextra
快速幂
ll qpow(ll a,ll b,ll p)
{
ll res = 1;
while(b)
{
if(b&1) res = (res*a)%p;
a = (a*a)%p;
b = b>>1;
}
return res;
}
字符串哈希
本质就是 base 进制数,所以有以下公式:
其中
pair<ull,ull> hashh(const string &s)
{
const int b = 131;const ull p1 = 1e9+7,p2 = 1e9+9;
ull h1 = 0,h2 = 0;
for(int i=0;i<s.size();i++)
{
h1 = ((1ull*h1*b)%p1+(1ull*s[i])%p1)%p1;
h2 = ((1ull*h2*b)%p2+(1ull*s[i])%p2)%p2;
}
return make_pair(h1,h2);
}
单调队列 单调栈
单调队列
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N = 1e6+5;
int n,k,a[N];
deque <pair<int,int> > q;
int main()
{
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++)
{
while(!q.empty()&&q.back().first>a[i]) q.pop_back();
q.push_back(mp(a[i],i));
while(!q.empty()&&q.front().second<=i-k) q.pop_front();
if(i >= k) cout << q.front().first << ' ';
}
q.clear();
cout << "\n";
for(int i=1;i<=n;i++)
{
while(!q.empty()&&q.back().first<a[i]) q.pop_back();
q.push_back(mp(a[i],i));
while(!q.empty()&&q.front().second<=i-k) q.pop_front();
if(i >= k) cout << q.front().first << ' ';
}
return 0;
}
单调栈
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N = 3e6+5;
int n,a[N],f[N];
deque <pair<int,int> > q;
int main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++)
{
while(!q.empty()&&a[i]>q.back().first)
{
f[q.back().second] = i;
q.pop_back();
}
q.push_back(mp(a[i],i));
}
for(int i=1;i<=n;i++) cout << f[i] << ' ';
return 0;
}
最小生成树
考场打过不写了
并查集
MST 要用,所以肯定会()
LCA
倍增写法
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N = 5e5+5;
int n,m,s;
// Graph
struct Edge
{
int nxt,to;
}e[2*N];
int h[N],cnt;
inline void add(int u,int v){ e[++cnt] = Edge{h[u],v}; h[u] = cnt; }
// lca
int f[20][N],d[N];
void dfs(int u)
{
for(int i=h[u];i;i=e[i].nxt)
{
int v = e[i].to;
if(v==f[0][u]) continue;
f[0][v] = u;
d[v] = d[u]+1;
dfs(v);
}
}
void init()
{
for(int j=1;j<=18;j++)
for(int i=1;i<=n;i++)
f[j][i] = f[j-1][f[j-1][i]];
}
int lca(int x,int y)
{
if(d[x]<d[y]) swap(x,y);
for(int j=18;j>=0;j--) if(d[f[j][x]]>=d[y]) x = f[j][x];
if(x == y) return x;
for(int j=18;j>=0;j--)
if(f[j][x]!=f[j][y]) x=f[j][x],y=f[j][y];
return f[0][x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> m >> s;
for(int i=1,x,y;i<n;i++)
{
cin >> x >> y;
add(x,y),add(y,x);
}
d[s] = 1;
dfs(s);
init();
for(int i=1,x,y;i<=m;i++)
{
cin >> x >> y;
cout << lca(x,y) << '\n';
}
return 0;
}
Dijistra
int dis[N];
void dijistra(int s)
{
priority_queue <pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
int vis[N];
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
q.push(mp(0,s));dis[s]=0;
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to,w=e[i].val;
dis[v]=min(dis[u]+w,dis[v]);
q.push(mp(dis[v],v));
}
}
}
SPFA
bool spfa(int s)
{
queue <int> q;
int vis[N],cnt[N];
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
dis[s] = 0,vis[s] = 1;q.push(s);cnt[s]++;
while(!q.empty())
{
int u = q.front();q.pop();vis[u] = 0;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to,w=e[i].val;
if(dis[u]+w>=dis[v]) continue;
dis[v]=dis[u]+w;
if(vis[v]) continue;
q.push(v);
vis[v] = 1; // 这里不要漏了
if(++cnt[v]>=n) return 1;
}
}
return 0;
}
拓扑排序
int ru[N];
void topo()
{
queue <int> q;
for(int i=1;i<=n;i++) if(!ru[i]) q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
// dp
if(!(--ru[v])) q.push(v);
}
}
}
差分约束
建模而已,记得超级源点即可。
ST 表
void init()
{
lg2[1] = 0;
for(int i=2;i<=100000;i++) lg2[i] = lg2[i>>1]+1;
for(int i=1;i<=n;i++) f[0][i] = a[i];
for(int j=1;j<=lg2[n];j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[j][i] = max(f[j-1][i],f[j-1][i+(1<<(j-1))]);
}