如果读者想打印/复习,欢迎访问下方的github
链接进行下载,上传了md和pdf版本,更方便阅读/使用
github
地址:https://github.com/Capsfly/sducs-tpp
1. scanf printf 输入输出优化
double :%lf
long long:%lld
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
用"\n"而不是endl
2. mod运算
a+b: (a%MOD+b%MOD)%MOD
a-b: ((a-b)%MOD+MOD)%MOD
3. 二分
第一种
int main()
{
int l;
int r;
while(l < r)
{
int mid = (l + r)/ 2;
if(check())
{
r = mid; // 这里是 r = mid, 说明[l,mid]是合法范围
}
else
{
l = mid + 1; // [l,mid]这个范围都不是合法范围,所以下一次查找直接从 l = mid + 1开始了
}
//最后的l,r是答案 因为 l == r ,最终就是答案。
}
}
第2种
int main()
{
int l;
int r;
while(l < r)
{
int mid = (l + r + 1)/ 2; // 这里要 l + r +1 要不然会死循环
if(check())
{
l = mid; // mid这个位置 满足条件之后 查找 [mid , right]的位置, 所以l移到mid的位置
}
else
{
r = mid - 1; // [mid,r] 不满足条件, 所以要移到满足条件的一方, r = mid - 1
}
}
//最后的l,r是答案 因为 l == r
}
4. 单调栈
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;
int a[N];
int l[N];
int r[N];
int n;
stack<pair<int, int>>s1;
stack<pair<int, int>>s2;
int ans;
signed main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
while (!s1.empty()&&s1.top().second>=a[i])//左边第一个小于它的
{
s1.pop();
}
if (s1.empty())
{
l[i] = 0;
}
else
{
l[i] = s1.top().first;
}
s1.push({ i,a[i] });
}
for (int i = n; i ; i--)
{
while (!s2.empty() && s2.top().second >= a[i])
{
s2.pop();
}
if (s2.empty())
{
r[i] = n+1;
}
else
{
r[i] = s2.top().first;
}
s2.push({ i,a[i] });
}
for (int i = 1; i <= n; i++)
{
int l1 = l[i] + 1;
int r1 = r[i] - 1;
int length = r1 - l1 + 1;
ans = max(ans, length * a[i]);
}
cout << ans;
return 0;
}
5. kruskal
```c++
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=4e5+50;
struct edge
{
int a,b,w;
bool operator<(const edge&e)
{
return w<e.w;
}
};
edge e[N];
int fa[N];
int find(int u)
{
if (u!=fa[u])
{
fa[u]=find(fa[u]);
}
return fa[u];
}
void merge(int a,int b)
{
a=find(a);
b=find(b);
fa[a]=b;
}
int n,m;
void kruskal()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
int cnt=0;
int ans=0;
sort(e+1,e+1+m);
for(int i=1;i<=m;i++)
{
int a=e[i].a;
int b=e[i].b;
if (find(a)!=find(b))
{
ans+=e[i].w;
merge(a,b);
cnt++;
}
}
// cout<<cnt<<endl;
if (cnt==n-1)
{
cout<<ans<<endl;
}
else
{
cout<<"impossible"<<endl;
}
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>e[i].a>>e[i].b>>e[i].w;
}
kruskal();
return 0;
}
6. prim
#include <bits/stdc++.h>
using namespace std;
const int N=2*500+10;
int g[N][N];
int n,m;
const int INF=0x3f3f3f3f;
const int fill_val=0x3f;
bool vis[N];
int dis[N];
int ans;
void prim()
{
memset(dis,fill_val,sizeof dis);
dis[1]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&(t==-1||dis[j]<dis[t]))
{
t=j;
}
}
if(dis[t]==INF)
{
printf("impossible");
return;
}
ans+=dis[t];
vis[t]= true;
for(int j=1;j<=n;j++)
{
dis[j]=min(dis[j],g[t][j]);
}
}
printf("%d",ans);
}
int main()
{
scanf("%d%d",&n,&m);
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=j)
{
g[i][j]=INF;
}
}
}*/
memset(g,fill_val,sizeof g);
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[v][u]=g[u][v]=min(g[u][v],w);
}
prim();
return 0;
}
7. dijkstra
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+50;
//int belong[N];
//vector<int>block[N];
int d[N];
bool vis[N];
int h[N];
int ne[N];
int w[N];
int target[N];
int idx=1;
void add(int a,int b,int c)
{
target[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int n,m;
#define pii pair<int,int>
void dijkstra()
{
memset(d,0x3f,sizeof d);
d[1]=0;
priority_queue<pii,vector<pii>,greater<pii>>q;
q.push({0,1});
while (!q.empty())
{
auto t=q.top();
q.pop();
int v=t.second,dis=t.first;
if (vis[v])
{
continue;
}
vis[v]= true;
for(int i=h[v];i;i=ne[i])
{
int j=target[i];
if (d[v]+w[i]<d[j])
{
d[j]=d[v]+w[i];
q.push({d[j],j});
}
}
}
if (d[n]>0x3f3f3f3f)
{
cout<<-1<<endl;
}
else
{
cout<<d[n]<<endl;
}
}
signed main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
dijkstra();
return 0;
}
8. spfa最短路
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m;
const int N = 2e5 + 50;
int dis[N];
bool vis[N];
vector<pair<int, int>>to[N];// dest val
void add(int a, int b, int c)
{
to[a].push_back({ b,c });
}
void spfa()
{
memset(dis, 0x3f, sizeof dis);
dis[1] = 0;
queue<int>q;
q.push(1);
while (!q.empty())
{
auto t = q.front();
q.pop();
vis[t] = false;
for (auto& i : to[t])
{
int w = i.second;
int dest = i.first;
if (dis[t] + w < dis[dest])
{
dis[dest] = dis[t] + w;
if (!vis[dest])
{
vis[dest] = true;
q.push(dest);
}
}
}
}
if (dis[n] > 0x3f3f3f3f)
{
cout << "impossible";
}
else
{
cout << dis[n];
}
cout << endl;
}
signed main()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int x, y, z;
cin >> x >> y >> z;
add(x, y, z);
}
spfa();
return 0;
}
9. spfa求负环
#include <bits/stdc++.h>
using namespace std;
const int N=20000+50;
int n;
int w[N],h[N],ne[N],target[N];
int idx=1;
bool vis[N];
int dis[N];
void add(int a,int b,int c)
{
w[idx]=c;
target[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int m;
int cnt[N];
const int fill_val=0x3f;
const int INF=0x3f3f3f3f;
void spfa()
{
memset(dis,fill_val,sizeof dis);
dis[1]=0;
queue<int>q;
for(int i=1;i<=n;i++)
{
q.push(i);
vis[i]= true;
}
while (!q.empty())
{
auto t=q.front();
q.pop();
vis[t]= false;
for(int i=h[t];i;i=ne[i])
{
int j=target[i];
if(dis[t]+w[i]<dis[j])
{
dis[j]=dis[t]+w[i];
cnt[j]=cnt[t]+1;
if(cnt[j]>=n)
{
printf("Yes");
return;
}
if(!vis[j])
{
q.push(j);
}
}
}
}
printf("No");
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
spfa();
return 0;
}
10. kosaraju求强联通分量
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 50;
vector<int>g1[N];
vector<int>g2[N];
int scc_id;//强联通分量的id
int belong[N];//属于那个强联通
int br[N];//退出序列
int n, m;
int in[N];
bool vis1[N];
bool vis2[N];
int br_cnt;
void dfs1(int u)
{
for (auto& i : g1[u])
{
if (!vis1[i])
{
vis1[i] = true;
dfs1(i);
}
}
br[++br_cnt] = u;
}
void dfs2(int u)
{
for (auto& i : g2[u])
{
if (!vis2[i])
{
vis2[i] = true;
belong[i] = scc_id;
dfs2(i);
}
}
}
void kosaraju()
{
for (int i = 1; i <= n; i++)
{
if (!vis1[i])
{
vis1[i] = true;
dfs1(i);
}
}
for (int i = n; i; i--)
{
int j = br[i];
if (!vis2[j])
{
vis2[j] = true;
scc_id++;
belong[j] = scc_id;
dfs2(j);
}
}
for (int i = 1; i <= n; i++)
{
for (auto& j : g1[i])
{
if (belong[i]!=belong[j])
{
in[belong[j]]++;
}
}
}
int ans = 0;
for (int i = 1; i <= scc_id; i++)
{
if (!in[i])
{
ans++;
}
}
cout << ans;
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
g1[a].push_back(b);
g2[b].push_back(a);
}
kosaraju();
return 0;
}
11. 树状数组
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=10e5+50;
int a[N];
int s[N];
int n,m;
int lb(int v)
{
return -v&v;
}
int getAnswer(int pos)
{
int ans=0;
for(int i=pos;i;i-=lb(i))
{
ans+=s[i];
}
return ans;
}
void update(int pos,int v)
{
for(int i=pos;i<=n;i+=lb(i))
{
s[i]+=v;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int val;
cin>>val;
update(i,val);
}
for(int i=0;i<m;i++)
{
int flag,x,y;
cin>>flag>>x>>y;
if (flag==1)
{
update(x,y);
}
else
{
cout<<getAnswer(y)-getAnswer(x-1)<<endl;
}
}
return 0;
}
12. 线段树
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lc 2*pos
#define rc lc+1
int n,m;
const int N=6e5+50;
int a[N];
int s[N*4];
int p,v;
int getAnswer(int pos,int l,int r,int p1,int p2)
{
if (l==p1&&r==p2)
{
return s[pos];
}
int mid=l+r>>1;
if (p2<=mid)
{
return getAnswer(lc,l,mid,p1,p2);
}
else if (p1>mid)
{
return getAnswer(rc,mid+1,r,p1,p2);
}
else
{
int lc_ans=getAnswer(lc,l,mid,p1,mid);
int rc_ans=getAnswer(rc,mid+1,r,mid+1,p2);
return lc_ans+rc_ans;
}
}
void update(int pos,int l,int r)
{
if (l==r)
{
s[pos]+=v;
return ;
}
int mid=l+r>>1;
if (p<=mid)
{
update(lc,l,mid);
}
else
{
update(rc,mid+1,r);
}
s[pos]=s[lc]+s[rc];
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
p=i;
v=a[i];
update(1,1,N);
}
for(int i=0;i<m;i++)
{
int flag,x,y;
cin>>flag>>x>>y;
if (flag==1)
{
p=x;
v=y;
update(1,1,N);
}
else
{
cout<<getAnswer(1,1,N,x,y)<<endl;
}
}
return 0;
}
13. 01背包
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2*1000+50;
int f[10][N];
int n,c;
int val[N];
int cost[N];
signed main()
{
cin>>n>>c;
for(int i=1;i<=n;i++)
{
cin>>cost[i]>>val[i];
}
for(int j=1;j<=c;j++)
{
if(j>=cost[1])
{
f[1][j]=val[1];
}
}
for(int i=2;i<=n;i++)
{
int now=i&1;
int pre=(i-1)&1;
for(int j=0;j<=c;j++)
{
f[now][j]=f[pre][j];
if (j>=cost[i])
{
f[now][j]=max(f[now][j],f[pre][j-cost[i]]+val[i]);
}
}
}
cout<<f[n&1][c];
return 0;
}
14. 完全背包
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2*1000+50;
int f[10][N];
int n,c;
int val[N];
int cost[N];
signed main()
{
cin>>n>>c;
for(int i=1;i<=n;i++)
{
cin>>cost[i]>>val[i];
}
for(int i=1;i<=n;i++)
{
int now=i&1;
int pre=(i-1)&1;
for(int j=1;j<=c;j++)
{
f[now][j]=f[pre][j];
if (j>=cost[i])
{
f[now][j]=max(f[now][j],f[now][j-cost[i]]+val[i]);
}
}
}
cout<<f[n&1][c];
return 0;
}
15. 多重背包
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2*2000+50;
int f[10][N];
int n,c;
int val[N];
int cost[N];
int num[N];
vector<int>af_val;
vector<int>af_cost;
vector<int>af_num;
signed main()
{
cin>>n>>c;
for(int i=1;i<=n;i++)
{
cin>>cost[i]>>val[i]>>num[i];
}
for(int i=1;i<=n;i++)
{
int start=1;
int backup=num[i];
while (backup-start>=0)
{
af_val.push_back(start*val[i]);
af_cost.push_back(start*cost[i]);
af_num.push_back(start);
backup-=start;
start*=2;
}
if (backup)
{
af_val.push_back(backup*val[i]);
af_cost.push_back(backup*cost[i]);
af_num.push_back(backup);
}
}
// 0 1
for(int i=0;i<af_num.size();i++)
{
int now=i&1;
int pre=(i-1)&1;
for(int j=0;j<=c;j++)
{
f[now][j]=f[pre][j];
if (j>=af_cost[i])
{
f[now][j]=max(f[now][j],f[pre][j-af_cost[i]]+af_val[i]);
}
}
}
cout<<f[(af_num.size()-1)&1][c];
return 0;
}
16. 分组背包
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2 * 2000 + 50;
int f[10][N];
vector<pair<int, int>>v[N];// cost val
int n, c;
signed main()
{
cin >> n >> c;
for (int i = 1; i <= n; i++)
{
int s;
cin >> s;
for (int j = 0; j < s; j++)
{
int val, cost;
cin >> cost >> val;
v[i].push_back({ cost,val });
}
}
for (int i = 1; i <= n; i++)
{
int now = i & 1;
int pre = (i - 1) & 1;
for (int j = 0; j <= c; j++)
{
f[now][j] = f[pre][j];
for (int k = 0; k < v[i].size(); k++)//填入哪个物品
{
if (j >= v[i][k].first)
{
f[now][j] = max(f[now][j], f[pre][j - v[i][k].first] + v[i][k].second);
}
}
}
}
cout << f[n & 1][c];
return 0;
}
17. 矩阵快速幂
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=20;
int n,p;
struct matrix
{
int a[N][N];
int row;
int col;
matrix(int row,int col):row(row),col(col)
{
memset(a,0,sizeof a);
}
matrix(const matrix&m)
{
memcpy(a,m.a,sizeof m.a);
row=m.row;
col=m.col;
}
matrix operator*(matrix&m)
{
matrix temp(row,m.col);
for(int i=1;i<=row;i++)
{
for(int j=1;j<=m.col;j++)
{
for(int k=1;k<=col;k++)
{
temp.a[i][j]+=(a[i][k]*m.a[k][j])%p;
temp.a[i][j]%=p;
}
}
}
return temp;
}
matrix ones(int row)
{
matrix ans(row,row);
for(int i=1;i<=row;i++)
{
ans.a[i][i]=1;
}
return ans;
}
void fast_pow(int num)
{
matrix ans=ones(row);
matrix t_m=*this;
int t=num;
while (t)
{
if (t&1)
{
ans=t_m*ans;
}
t_m=t_m*t_m;
t>>=1;
}
*this=ans;
}
};
int t;
signed main()
{
cin>>t;
for(int i=0;i<t;i++)
{
cin>>n>>p;
if (n<=2)
{
cout<<1<<endl;
}
else
{
matrix m(2,2);
m.a[1][1]=m.a[1][2]=m.a[2][1]=1;
m.fast_pow(n-2);
matrix src(2,1);
src.a[1][1]=1;
src.a[2][1]=1;
matrix ans=m*src;
cout<<ans.a[1][1]<<endl;
}
}
return 0;
}