@hhzhhzhhz
2024-12-21T18:24:10.000000Z
字数 6922
阅读 410
#include<bits/stdc++.h>using namespace std;int main(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);fclose(stdin);fclose(stdout);retrun 0;}
写不对就不写
scanf printf 不香吗?
while(l<r) {mid=(l+r+1)>>1;if(judge(mid)) l=mid;r=mid-1;}
while(l<r) {mid=(l+r)>>1;if(judge(mid)) r=mid;l=mid+1;}
init(){//初始化for(int i=1;i<=n;i++){f[i]=i;}}
get(int a){//查if(a==f[a]) return a;else return f[a]=get(f[a]);//路径压缩}
merge(int a,int b){//并int fa,fb;fa=get(a);fb=get(b);f[fa]=fb;}
#include<queue> //用到写一下,加.后可以弹出索引// FIFO(First In First Out)queue<int > q;//定义 qq.push(x); //将x压入q(队尾)q.pop(x); //弹出队首q.front(); //取队首q.back(); //取队尾q.size(); //元素数q.empty(); //队列是否为空
可以用于做可反悔的贪心
#include<queue>priority_queue<int > q1;//定义一个大根堆priority_queue<int ,vector<int> ,greater<int> > q2;//定义一个小根堆q1.top(); //取堆顶q1.top(); //弹出堆顶q1.push(x); //压入xq1.size(); //元素数
- 优先队列->重载运算符实现结构体
#include<bits/stdc++.h>#include<queue>using namespace std;struct nod {int a,b;friend bool operator <(const nod &x,const nod &y) {//重载运算符以b为参数的大根堆return x.b<y.b;}}priority_queue<nod> q;int main() {int n;int t;scanf("%d",&n);for(int i=1; i<=n; i++) {scanf("%d %d %d",&p.a,&p.b,&t);if(t)q.push(p);else {cout<<q.top().a<<q.top().b;q.pop();}}return 0;}
#include<stack>//LIFO Last In First Outstack<int > s;stack<int >s;s.size(); //元素数s.top(); //取栈顶s.pop(); //弹出栈顶s.push(x); //压入xs.empty(); //判断是否为空
->方便查询和处理字符串等。
#include<map>map<string,int> m2;map<int,int> m1;m1[a]=b;//赋值m1.find(x)==m1.end() //判断是否有x这个元素
???????merge(int l1 , int r1,int l2,int r2) {int cnt=0,p=0;while(l1<=r1&& l2<=r2)if(a[l1]<=a[l2]) t[++cnt]=a[l1++];else {// ans[++num][4]=a[l1];// ans[num][5]=a[l2]; 存逆序对t[++cnt]=a[l2++];}while(l1<=r1) t[++cnt]=a[l1++];while(l2<=r2) t[++cnt]=a[l2++];for(int i=l1; i<=r2; i++) {a[i]=t[++p];}}merge_sort(int l,int r) {int mid=(l+r)>>1;if(l<r) {merge_sort(l,mid);merge_sort(mid+1,r);merge(l,mid,mid+1,r);}}
#include "stdio.h"int count=0;void Merge(int r[],int r1[],int s,int m,int t) { // 合并子序列int i=s,j=m+1,k=s;int b;while(i<=m && j<=t) {if(r[i]<=r[j]) { // 取较小者放入r1[k]中r1[k++]=r[i++];} else {count+=m-i+1; // 若左边数大于右边数,则左边数及其后边数都大于该右边数b=i;while(b<=m) {printf("[%d,%d]\n",r[b],r[j]);b++;}r1[k++]=r[j++];}}while(i<=m) // 若第一个子序列没处理完,则进行收尾处理;下同r1[k++]=r[i++];while(j<=t)r1[k++]=r[j++];}void MergeSort(int r[],int s,int t) { // 对序列r[s]~r[t]进行归并排序int m,r1[1000],i;if(s==t)return ;else {m=(s+t)/2; // 划分MergeSort(r,s,m); // 子问题1MergeSort(r,m+1,t); // 子问题2Merge(r,r1,s,m,t); // 合并for(i=s; i<=t; i++)r[i]=r1[i];}}int main() {int r[]= {1,2,4,3,7,6,5,1},i;MergeSort(r,0,7); // 三个参数分别为待查数组、起始下标、截止下标for(i=0; i<=7; i++)printf("%d ",r[i]);printf("\n一共 %d个逆序对\n",count);}
要先确定要求的再f[][]表示什么
再确定动态转移方程
- 01背包
一个物品只能用一次
eg:洛谷 采药
for(int i=1;i<=n;i++){for(int j=v;j>=w[i];j++{f[j]=max(f[j],f[j-w[i]]+v[i]);}}
2. 完全背包
物品可以用无限次
eg:洛谷 疯狂的采药
for(int i=1;i<=n;i++){for(int i=w[i];i<=v;i++){f[j]=max(f[j],f[j-w[i]]+v[i]);}}
3. LIS Longest Increasing Subsequence
eg:洛谷 p1091 合唱队形
void lis() {for(int i=1; i<=n; i++) {for(int j=0; j<i; j++) {if(a[i]>a[j]) f[i]=max(f[i],f[j]+1);}}}
//该题用nologn 的方法求得 最长不上升子序列 和 最长上升子序列 板子有备无患#include<bits/stdc++.h>using namespace std;int a[100010];int f1[100010],f2[100010],len1=1,len2=1;//f1求最长不上升子序列//f2求最长上升子序列 即 第二问的解//bool cmp(int a,int b) {// return a>b;//}int main() {int n=0;while(scanf("%d",&a[++n])!=EOF);f1[1]=a[1];f2[1]=a[1];for(int i=2; i=a[i]) f1[++len1]=a[i];//满足条件接上else *upper_bound(f1+1,f1+1+len1,a[i],greater ())=a[i];//主要目的是为了将最后一个的数值尽可能放到最大使之后能放入的个数增加 达到序列最长的目的// else *upper_bound(f1+1,f1+1+len1,a[i],cmp)=a[i];// upper_bound 与 lower_bound 返回值为地址,加*直接修改地址所对应的值// 两个函数分别为求在一个右半开的升序序列中求在自左向右第一个大于(等于)x的值的地址 upper为大于 lower为大于等于// 在此升序是对于比较器而言的升序,故可以更改比较器,写个cmp,或直接用 greater () 改为在 降序序列中找到第一个小于(等于)x的值的地址if(f2[len2] < a[i]) f2[++len2]=a[i];else *lower_bound(f2+1,f2+1+len2,a[i])=a[i];}cout << len1 << endl << len2;return 0;}
5. LCS Longest common Subsequence
//核心代码void lcs() {// f[i][j]表示在a第i位前和b第j位前的lcsfor(int i=1; i<=n1; i++) {for(int j=1; j<=n2; j++) {if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1;if(a[i]!=b[j]) f[i][j]=max(f[i-1][j],f[i][j-1]);}}}
#include<bits/stdc++.h>using namespace std;int ver[10010];//该边终点int nxt[10010];//下一条边int head[10010];//表头int va[10010];//该边权值int cnt;void add(int x,int y,int v) {//加边cnt++;ver[cnt]=y;// 终点nxt[cnt]=head[x]; //把下一条边指向x原来的第一条边head[x]=cnt;//使x下的这条边成为第一条边va[cnt]=v;//赋权值}int bl(int x) {for(int i=head[x]/*第一条边*/;i; i=nxt[i]){//遍历// va[i]; //这边权值// ver[i];//这条边指向的点}}int main() {int n;scanf("%d",&n);int x,y,v;for(int i=1; i<=n; i++) {cin>>x>>y>>v;add(x,y,v);// add(y,x,v);无向图}bl(1);}
1. Dijkstra
2. SPFA
3. Floyd
#include<bits/stdc++.h>#include<queue>using namespace std;const int bn=10010,dn=10010;//最大边数、最大点数int head[dn],v[2*bn],ver[2*bn],nxt[2*bn];int cnt;void add(int x,int y,int va) {cnt++;nxt[cnt]=head[x];head[x]=cnt;ver[cnt]=y;v[cnt]=va;}int vis[10010];int dis[10010];void spfa(int s) {memset(dis,0x3f,sizeof(dis));queue<int > q;//存下一步要去的点q.push(s);dis[s]=0;vis[s]=1;while(!q.empty()) {int x=q.front();q.pop();vis[x]=0;for(int i=head[x]; i; i=nxt[i]) {//枚举边int to=ver[i],va=v[i];//找到去的点,和路上的权值if(dis[to]>dis[x]+va) {dis[to]=dis[x]+va;if(!vis[to]) {q.push(to);vis[to]=1;}}}}}int main() {int n;scanf("%d",&n);//输入边数int x,y,v;for(int i=1; i<=n; i++) {scanf("%d %d %d",&x,&y,&v);add(x,y,v);add(y,x,v);}int s;scanf("%d",&s);spfa(s);for(int i=1; i<=n; i++)printf("%d\n",dis[i]);return 0;}
#include<bits/stdc++.h>using namespace std;const int MN=510;int dis[MN][MN];int main() {int n,m,q;int x,y,z;memset(dis,0x3f,sizeof(dis));scanf("%d %d %d",&n,&m,&q);//边数 点数 询问次数;for(int i=1;i<=m;i++){dis[i][i]=0;}for(int i=1; i<=n; i++) {scanf("%d %d %d",&x,&y,&z);dis[x][y]=z;dis[y][x]=z;}for(int k=1; k<=n; k++) {for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}}}for(int i=1; i<=q; i++) {scanf("%d %d",&x,&y);printf("%d",dis[x][y]);}return 0;}
#include<bits/stdc++.h>using namespace std;int n,m,fa[5010],ans,cnt;struct nod {int fr,to,v;} a[200010];inline int get(int x) {if(x==fa[x]) return x;return fa[x]=get(fa[x]);}inline int merge(int a,int b) {int f_a=get(a),f_b=get(b);fa[f_a]=f_b;}bool cmp(nod a,nod b) {return a.v<b.v;}void kruskal() {for(int i=1; i<=m; i++) {int u=get(a[i].fr);int v=get(a[i].to);if(u==v) continue;//在并查集里-即已经有一条更短的路在树中else {fa[u]=v;ans+=a[i].v;cnt++;}if(cnt==n-1) return;//即已形成树}}int main() {scanf("%d %d",&n,&m);for(int i=1; i<=n; i++) fa[i]=i;for(int i=1; i<=m; i++) {scanf("%d %d %d",&a[i].fr,&a[i].to,&a[i].v);}sort(a+1,a+1+m,cmp);//按照边长升序排列kruskal();printf("%d",ans);return 0;}
#include<bits/stdc++.h>using namespace std;int n;int f[200010][20];int main() {scanf("%d",&n);for(int i=1; i<=n; i++) {scanf("%d",&f[i][0]);}int m,l,r;int k=2;for(int j=1; j<=19; j++) {for(int i=1; i+k-1<=n; i++) {f[i][j]=max(f[i][j-1],f[i+(k>>1)][j-1]);}k*=2;}scanf("%d",&m);for(int i=1; i<=m; i++) {scanf("%d%d",&l,&r);int t=log(r-l+1)/log(2);//换底公式int x=pow(2,t);printf("%d\n",max(f[l][t],f[r-x+1][t]));//将没有表示过的【l,r】,变为已经表示过的两端}return 0;}
#include<bits/stdc++.h>using namespace std;long long poww(long long a,long long b) {int res=1,x=a;while(b>0) {if(b&1) res=res*x;x=x*x;b>>=1;}return res;}int main() {long long a,b;scanf("%lld %lld",&a,&b);printf("%lld",poww(a,b));return 0;}
bool cmp(node a, node b){if(a.x != b.x){ // 如果两个 x 不等则以 x 的大小排序return a.x > b.x;}return a.y > b.y; // 否则以 y 的大小排序}sort(c + 1, c + 1001, cmp);