模板整理(一)
来源:互联网 发布:影后春夏 知乎 编辑:程序博客网 时间:2024/06/05 02:15
1并查集(8-2)
int find(int x) //查找我(x)的掌门
{
int r=x; //委托 r 去找掌门
while (pre[r ]!=r) //如果r的上级不是r自己(也就是说找到的大侠他不是掌门 = =)
r=pre[r ] ; // r 就接着找他的上级,直到找到掌门为止。
return r ; //掌门驾到~~~
int i=x, j; (合并)
while(i!=r)
{
j=pre[i];
pre[i]=r;// r是不是最后的父亲节点?
r=j;
}
}
void join(int x,int y) //我想让虚竹和周芷若做朋友
{
int fx=find(x),fy=find(y); //虚竹的老大是玄慈,芷若MM的老大是灭绝
if(fx!=fy) //玄慈和灭绝显然不是同一个人
pre[fx ]=fy; //方丈只好委委屈屈地当了师太的手下啦
}
2深度优先搜索(dfs)和 广度优先搜索 (bfs)
dfs/
void dfs(int x,int y)
{if(x<1||x>m||y<1||y>n)return ;// 函数返回值为空if(s[x][y]!='@')//这个if语句的作用很大return ;s[x][y]='*';//标记 for(int i=-1 ; i<=1 ; i++)for(int j=-1 ; j<=1 ; j++) //八个方向{//也有另外一种写法 即用数组表示dfs(x+i,y+j);}//这一步递归真的好厉害}
3.快速幂
//快速幂
- int pow3(int a,int b)
- {
- int ans = 1,base = a;
- while(b!=0)
- {
- if(b&1) //?b==1
- ans *= base;
- base *= base;
- b>>=1; //b/2
- }
- return ans;
- }
4.素数打表
筛选法求素数也重要的求素数方法之一。这种方法主要用于打素数表,如求出n之内的所有素数,其思路是从1开始遇到一个素数就标记一下,并去掉n之内的大于它的所有倍数,直循环到n:#include<stdio.h>int n,i,j,a[1000001],p[100000],t=0;void main(){ scanf("%d",&n); a[1]=0; for(i=2;i<=n;i++)a[i]=1; for(i=2;i<=n;i++) if(a[i]){ p[t++]=i;//i即为被记录的素数 for(j=i+i;j<=n;j+=i)a[j]=0;//素数的倍数都标记为零 } for(i=0;i<t;i++) printf("%d%c",p[i],i<t-1?' ':'\n');}此方法也有局限性,数据量中等时才不会超时,数据量过大时也会超时,而且只能用素数打表,不能对单个数进行判定!(3)这是我根据《离散数学》上的一个定理想到的,定理为:“若正整数a>1,且a不能被不超过a的平方根的任一素数整除,则a是素数”,实现过程如下:#include<stdio.h>#include<math.h>int p[1000000],a[10000001],t=0;int prime(int n){ int i,q; q=(int)sqrt(n); for(i=0;p[i]<=q&&t;i++) if(n%p[i]==0)return 0;//要不要初始化p【0】? return 1;}int main(){ int n,i; scanf("%d",&n); for(i=2;i<=n;i++) if(prime(i))p[t++]=i;//这个地方的i,即为上面函数的实参 for(i=0;i<t;i++)//这个if语句能不能实现->运行了一下可以实现 printf("%d%c",p[i],i<t-1?' ':'\n');}此方法可以对超大量数据的进行打表!此方法也同样合适于素数打表,判定单个时这个方法不可取!
5. gcd lcm
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;//递归
}
6. 二分
7 栈和队列
8 贪心
9 最小生成树
struct node //结构体
{
int from,to,len;
}edge[maxn];
int n,fa[maxn],m,ans,q;
bool cmp(node a,node b)
{
return a.len<b.len;
}
int Find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=Find(fa[x]);//并查集
}
void Merge(int x,int y)
{
x=Find(x),y=Find(y);
if(x!=y)
fa[y]=x;
}
(此处为模板,上面是可能会用到的一些函数)
int Kruskal()//最小生成树{
sort(edge,edge+m,cmp);
//对边进行排序,同时整个结构体的元素随着边的排序而排序
for(int i=0;i<n;i++)//初始化fa[i]=i;
ans=0;
for(int i=0; i<m ;i++)
if(Find(edge[i].from)!=Find(edge[i].to))//连接 避免成环 这步很重要
{
Merge(edge[i].from,edge[i].to);
ans+=edge[i].len;//计数
}
return ans;
}
普利姆算法
- void prim(){
- for(i=1;i<=n;i++){
- dis[i]=map[1][i];
- pre[i]=-1; //map存两点距离,dis存未收入点到收入点距离,pre存该点的父结点
- }
- dis[1]=0;
- pre[1]=0;
- int sum=0,flag,minn;
- for(i=2;i<=n;i++){
- minn=inf;
- for(j=1;j<=n;j++){
- if(pre[j]==-1&&dis[j]<minn){
- flag=j;
- minn=dis[j];
- }
- }
- pre[flag] = i;
- sum+=minn;
- for(j=1;j<=n;j++){
- if(pre[j]==-1&&dis[j]>map[flag][j])
- //更新未收入点到已收入点的最短距离
- dis[j]=map[flag][j];
- }
- }
- printf("%d\n",sum);
- }
10·博弈
11·LIS(最长上升子序列)
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN =1010;
int a[MAXN]; int maxLen[MAXN];
int main()
int N; cin >> N;
for( int i = 1;i <= N;++i)
cin >> a[i]; maxLen[i] = 1; //初始化
}
for( int i = 2; i <= N; ++i)
//每次求以第i个数为终点的最长上升子序列的长度
for( int j = 1; j < i; ++j)
//察看以第j个数为终点的最长上升子序列
if( a[i] > a[j] )
maxLen[i] = max(maxLen[i],maxLen[j]+1); //状态转移方程
cout << * max_element(maxLen+1,maxLen + N + 1 ); //且记录最长的那个上升序列
return 0; //有趣的输出方法
} //时间复杂度O(N2)
“人人为我”递推型动归程序
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 30010;
int dp[maxn], a[maxn];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
int ans=0;
for(int i=0;i<n;++i)
{
dp[i]=1;
for(int j=0;j<i;++j)
{
if(a[j]<a[i])
dp[i] = max(dp[i], dp[j]+1);
}
ans=max(dp[i],ans);
}
printf("%d\n",ans);
}
return 0;
}
//O(nlogn)
#include <cstdio>
#include <algorithm>
#define INF 0x3f3f3f
using namespace std;
int dp[30010],a[30010];
int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;++i)
{
scanf("%d",&a[i]);
dp[i]=INF;
}
for(i=0;i<n;++i)
*lower_bound(dp,dp+n,a[i])=a[i];
printf("%d\n",lower_bound(dp,dp+n,INF)-dp);
} //lower_bound()在last和first之间进行二分查找 前闭后开
return 0; //返回第一个大于或等于val的位置
}
12.LDS(最长公共子序列)
#include <cstring>
using namespace std;
char sz1[1000];
char sz2[1000];
int maxLen[1000][1000]; //maxLen[i][j]表示第一个串的前i个数字
while( cin >> sz1 >> sz2 ) {
int length1 = strlen( sz1);
int length2 = strlen( sz2);
int i,j;
for( i = 0;i <= length1; i ++ ) //初始化
maxLen[i][0] = 0;
for( j = 0;j <= length2; j ++ )
maxLen[0][j] = 0;
for( i = 1;i <= length1;i ++ ) {
for( j = 1; j <= length2; j ++ ) {
if( sz1[i-1] == sz2[j-1] )
maxLen[i][j] = maxLen[i-1][j-1] + 1;
else
maxLen[i][j] = max(maxLen[i][j-1], //取最大的一个
maxLen[i-1][j]);
}
}
cout << maxLen[length1][length2] << endl;
}
return 0;
}
13.树状数组
#include<cstdio>
#include<cstring>
#define lowerBit(x) (x&(-x))
int num[10000];
int n;
void UpDate(int x,int y) //把第x个数加y
{
while (x <= n)
{
num[x] += y;
x = x+lowerBit(x);
}
}
int Query(int x) //求从1到x的和
{
int sum = 0;
while (x > 0)
{
sum += num[x];
x = x-lowerBit(x);//x&(x-1)
}
return sum;
}
int main()
{
scanf ("%d",&n);
memset(num,0,sizeof(num));
for (int i = 1 ; i <= n ; i++)
{
int t;
scanf ("%d",&t);
UpDate(i,t);
}
int m;
scanf ("%d",&m);
while (m--)
{
int x,y;
scanf ("%d %d",&x,&y);//看不懂
printf ("%d\n",Query(y)-Query(x-1));
}
return 0;
}
14.线段树 //看不懂
struct Node//不要左右子节点指针的做法
{
int L,R;
int minV,maxV;
int Mid()
{
return (L+R)/2;//还有这操作
}
};
Node tree[800010]; //4倍叶子节点数量就够
void BuildTree(int root, int L, int R)
{
tree[root].L = L;
tree[root].R = R;
tree[root].minV = INF;//这是为什么?到底哪个是大的
tree[root].maxV = -INF;//那个是小的?
if(L!=R)
{
BuildTree(2*root+1, L, (L+R)/2);
BuildTree(2*root+2, (L+R)/2+1, R);
}
}
void Insert(int root, int i, int v)
//将第i个数,其值为v,插入线段树
{
if(tree[root].L == tree[root].R)//成立则亦有tree[root].R==i
{
tree[root].minV = tree[root].maxV = v;
return ;
}
tree[root].minV = min(tree[root].minV , v);
tree[root].maxV = max(tree[root].maxV , v);
if(i <= tree[root].Mid())
Insert(2*root + 1, i, v);
else
Insert(2*root + 2, i, v);
}
void Query(int root, int s, int e)
//查询区间[s,e]中的最大值和最小值,如果更优就记录在全局变量里
{
if( tree[root].minV >= minV && tree[root].maxV <= maxV )
return;
if( tree[root].L == s && tree[root].R == e )
{
minV = min( minV, tree[root].minV );
// minV = min( minV, tree[root].minV );
maxV = max( maxV, tree[root].maxV );
return ;
}
if( e <= tree[root].Mid() )
Query( 2*root + 1, s, e );
else if( s > tree[root].Mid() )
Query( 2*root + 2, s, e );
else
{
Query( 2*root + 1, s, tree[root].Mid() );
Query( 2*root + 2, tree[root].Mid() + 1, e );
}
}
15.KMP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//S: a b a b b a b a b a d a b a b a a a b a b a a
// j
// T: a b a b a a a b a b a a
// next :-1 0 0 1 2 3 1 1 2 3 4 5
char s[1000], t[1000];
int next[1000] = {-1, 0, 0, 1, 2, 3, 1, 1, 2, 3, 4, 5};
int Kmp(char* s, int n, char* t, int m) {
int i = 0, j = 0;
while(i < n) {
if(j == -1 || s[i] == t[j]) {
++i; ++j;
if(j == m) {
return i - m + 1;
}
}
else {
j = next[j];
}
}
return -1;
}
int main()
{
//ababababadababaaababaa
//ababaaababaa
//ababcabcacbab
//abc
scanf("%s%s", s, t);
int l1 = strlen(s);
int l2 = strlen(t);
printf("第一个匹配的位置%d\n", Kmp(s, l1, t, l2));
return 0;
}
//next[i]: 0 -> i-1 最大的前缀和后缀匹配的长度 0 -> n-1
//S: a b a b b a b a b a d a b a b a a a b a b a a
//T: a b a b a a a b a b a a
// -1 0 0 1 2 3 1 1 2 3 4 5
//从头选择next[j]个字符和从尾向前选择next[j]个字符是相等的
//
//1>, S串和T串前面这些字符是相等的
//2>, T串前面字符有next[j]前缀和后缀匹配的长度
16.二分图
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int f[500+5];//女和哪个男配对 bool fr[505][505];//可用vector<int> d[505]代替 bool vis[505];//标记数组,表示这个人搜索过 int k,n,m;bool find(int x)//寻找x男生,返回:能否找到人去匹配 {for (int i = 1 ; i <= m ; i++){if (fr[x][i] && !vis[i]){vis[i] = true;//首先标记if (f[i] == -1)//如果该女生没有和别人匹配 {f[i] = x;//则和该男生匹配 return true;//表示匹配完成 }else if (find(f[i]))//如果该女生匹配的男生可以找到其他的女生匹配{f[i] = x;//递归的思想return true;}}}return false;}int main(){while (~scanf ("%d",&k) && k){scanf ("%d %d",&n,&m);memset(f,-1,sizeof(f));//初始化,表示没有和任何人配对memset(fr,false,sizeof(fr));//初始化 for (int i = 1 ; i <= k ; i++){int x,y;scanf ("%d %d",&x,&y);fr[x][y] = true;}int ans = 0;//表示已经配对的男生数 for (int i = 1 ; i <= n ; i++){memset(vis,false,sizeof(vis));if (find(i))ans++;}printf ("%d\n",ans);}return 0;}
- 模板整理(一)
- 排序模板(整理)
- 模板(一)----->函数模板
- 2017年ACM模板(常用)弱渣整理 一、暴力
- 模板整理
- 一、代码生成器系列-T4模板学习整理
- 模板整理---大数模板
- gridview整理(一)
- cakephp整理(一)
- 面试整理(一)
- js整理(一)
- java整理(一)
- sqlalchemy整理(一)
- DP(一)整理
- C++模板(一)
- C++模板(一)
- 类模板(一)
- C++模板(一)
- Android 利用handler发送消息:"This message is already in use"错误
- 学习签名signature 的使用
- MySql避免重复插入记录方法(ignore,Replace,ON DUPLICATE KEY UPDATE)
- 转自:http://article.yeeyan.org/view/10947/42583?from_com jQuery性能优化指南 现在jquery应用的越来越多, 有些同学在享受爽快淋漓codi
- 去噪效果评价算法分析,SNR,PSNR,SSIM等的区别与优劣对比
- 模板整理(一)
- 程序员该听的几百首歌
- 两个大数相乘-Java
- mysql decimal
- 【线段树-思维】hdu 6047
- OpenGL学习——(4)小例子
- xshell连接kalix时,显示ssh服务器拒绝了密码
- Oracle使用正则表达式regexp_replace将表某列杂乱内容中所含的手机号码提取出来
- mysql查询奇数行