算法C++

枚举

1.化段为点

前缀和             eg:给一个数列,算x到y个数的和

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	int n;
	cin>>n;
	vector<int> a(n);
	vector<int> sum(n+1,0);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		sum[i+1]=sum[i]+a[i];
	}
	int x,y;
	cin>>x>>y;
	cout<<sum[y]-sum[x-1];
 }

给一段数字,q次访问,每次对[x,y]区间进行加减x,最后再重新给出新的一段数字

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	int n;
	cin>>n;
	vector<int> a(n+1,0);
	vector<int> cha(n+1,0);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		cha[i-1]=a[i]-a[i-1]; 
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		cha[x-1]+=z;
		cha[y]-=z;
	}
	for(int i=1;i<=n;i++)
	{
		a[i]=a[i-1]+cha[i-1];
		cout<<a[i]<<endl;
	}
}

n棵树,q次砍树区间为[x,y],求之后树总数量

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct sb
{
	int pos,num;
};

bool compare(sb x,sb y)
{
	if(x.pos == y.pos )
	{
		return x.num < y.num ;
	}
	return x.pos < y.pos ;
}

int main()
{
	int n,q;
	cin>>n>>q;
	vector<sb> a(q*2);
	for(int i=0;i<q;i++)
	{
		int x,y;
		cin>>x>>y;
		if(x>y)
		{
			int t=x;
			x=y;
			y=t;
		}
		a[i].pos=x-1;
		a[i].num=1;
		a[i+q].pos=y;
		a[i+q].num=-1;
	}
	sort(a.begin() , a.end() ,compare);
	int cnt=a[0].pos;
	int b=0;
	for(int i=0;i<q*2;i++)
	{
		b=b+a[i].num;
		if(b==1&&a[i].num==1&&i>0)
		{
			cnt+=a[i].pos-a[i-1].pos;
		}
	}
	cnt+=n-a[2*q-1].pos;
	cout<<cnt+1;
 } 

3bba9a30e9304b5f86bb137aa32eb0ec.jpeg

 输入n个数,有m区间可以缓存,求需要存多少

#include<iostream>

using namespace std;

int main()
{
	int n,m,cnt=0;
	cin>>n>>m;
	int v[n],a[n];
	for(int i=0;i<n;i++)
	{
		int x;
		cin>>x;
		if(v[x]==1)
		{
			continue;
		}
		a[cnt++]=x;
		v[x]=1;
		if(cnt>m)
		{
			v[a[cnt-m-1]]==0;
		}
	}
	cout<<cnt;
}

追逐法/双指针法/尺量法/蚯蚓法:一缩一进

#include<iostream>
#include <algorithm>
using namespace std;

int main()
{
	int n,s;
	cin>>n>>s;
	int a[n];
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	int len=n+1,r=0;
	int sum=0;
	for(int l=0;l<n;l++)
	{
		while(r<n&&sum<s)
		{
			sum+=a[r];
			r++;
		}
		if(sum>=s)
		{
			len=min(r-l,len);
		}
		else
		{
			break;
		}
		sum-=a[l];
	}
	if(len>n)
	{
		printf("0");
	}
	else
	{
		printf("%d",len);
	}
	return 0;
}

计算n个数,i到j最大差值

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    int n, maxx = 0;
    cin >> n;
    vector<int> a(n), minn(n);

    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }

    minn[n - 1] = a[n - 1];

    for (int j = n - 2; j >= 0; j--)
    {
        minn[j] = min(minn[j + 1], a[j]);
    }

    for (int i = 0; i < n; i++)
    {
        maxx = max(maxx, a[i] - minn[i]);
    }

    cout << maxx;

    return 0;
}

拼数:将n个数组装成最大数

字符串x+y就是例如233+2331=2332331这样,叠加起来

然后比较就是从头开始一个字符一个比

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

bool comp(string x,string y)
{
	return x+y>y+x;
}

int main()
{
    int n;
	cin>>n;
	vector<string> a(n);
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	sort(a.begin(),a.end(),comp);
	for(int i=0;i<n;i++)
	{
		cout<<a[i];
	}
}

长度为m,数字总和为s的最大值和最小值

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

int main()
{
    int m,s;
	cin>>m>>s;
	if(9*m<s||s<2)
	{
		return 0;
	}
	int qian=0;
	int zhong=s/9;
	if(zhong)
	{
		qian=s%9;
	}
	else
	{
		zhong=s;
	}
	const string a(qian, '9');
	const string b(m-qian-1, '0');
	const string c(m-qian-2, '0');
	cout<<"最大值:"<<a<<zhong<<b<<endl;
	cout<<"最小值:"<<'1'<<c<<zhong-1<<a;
}

国王左手右手金币         比较前后两个a,b来反映全局         "以偏概全"

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct lr
{
	int l,r;
};

bool comp(lr x,lr y)
{
	return x.l * x.r < y.l * y.r;
}

int main()
{
	int n;
	cin>>n;
	vector<lr> mult(n);
	for(int i=0;i<n;i++)
	{
		scanf("%d%d",&mult[i].l,&mult[i].r);
	}
	sort(mult.begin(),mult.end(),comp);
	long int maxx=0;
	long int sum=1;
	for(int i=0;i<n;i++)
	{
		sum=mult[i].l*sum;
		maxx=max(maxx,sum/(mult[i].r));//注意类型 
	}
	cout<<maxx;
 } 

fed27dd88e56465e8751f787f926327a.jpeg

由此处开始递归

我认为递归不要去想太多,直接以偏概全,用片面的想法去循环

归并排序--一分为二

#include <iostream>

using namespace std;

int n;
int a[1000],b[1000];

void hen(int l,int mid,int r)
{
	int q=l,p=mid+1;
	for(int i=l;i<=r;i++)
	{
		if(q>mid||(a[p]<=a[q]&&p<=r))
		{
			b[i]=a[p++];
		}
		else
		{
			b[i]=a[q++];
		}
	}
	for(int i=l;i<=r;i++)
	{
		a[i]=b[i];
	}
}

void erfen(int l,int r)
{
	if(l==r) return ;
	int mid=(l+r)/2;
	erfen(l,mid);
	erfen(mid+1,r);
	hen(l,mid,r);
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	erfen(0,n-1);
	for(int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
}

7db858a361c4486ba7ea0bfc4dd55e2a.jpeg

计算逆序对    修改上面代码

void hen(int l, int mid, int r)
{
    int q = l, p = mid + 1;
    for (int i = l; i <= r; i++)
    {
        if (q > mid || (a[p] <= a[q] && p <= r))
        {
            b[i] = a[p++];
            cnt += (mid - q + 1); // 更新逆序对的数量
        }
        else
        {
            b[i] = a[q++];
        }
    }
    for (int i = l; i <= r; i++)
    {
        a[i] = b[i];
    }
}

汉诺塔新解:这次就是按照上面我所说的直接列出来 

#include<iostream>

using namespace std;

int cnt=0;

void han(int n,char qi,char mo,char zhong)
{
	if(n==0) return ;
	han(n-1,qi,zhong,mo);//
	cout<<qi<<"->"<<mo<<endl;
	cnt++;
	han(n-1,zhong,mo,qi);
}

int main()
{
	int n;scanf("%d",&n);
	han(n,'x','z','y');
	cout<<cnt;
} 

递归计算器

#include <iostream>
#include <cstdlib>  // 包含 std::atof 函数的头文件
#include <cmath>
using namespace std;

string a;

double zhuan(int l, int r)
{
    string num_str(a.begin() + l, a.begin() + r);
    return std::atof(num_str.c_str());
}

double suan(int l,int r)
{
	int cnt=0;
	int pos1=-1,pos2=-1,pos3=-1;
	for(int i=l;i<r;i++)
	{
		if(a[i]=='(') cnt++;
		if(a[i]==')') cnt--;
		if(cnt==0)
		{
			if(a[i]=='+'||a[i]=='-') pos1=i;
			else if(a[i]=='*'||a[i]=='/') pos2=i;
			else if(a[i]=='^') pos3=i;
		}
	}
	if(pos1==-1&&pos2==-1&&pos3==-1)
	{
		if(cnt==0&&a[l]=='(') return suan(l+1,r-1);
		else if(cnt<0&&a[r]==')') return suan(l,r-1);
		else if(cnt>0&&a[l]=='(') return suan(l+1,r);
		return zhuan(l,r);
	}
	if(pos1!=-1)
	{
		if(a[pos1]=='+') return suan(l,pos1) + suan(pos1+1,r);
		else return suan(l,pos1) - suan(pos1+1,r);
	}
	else if(pos2!=-1)
	{
		if(a[pos2]=='*') return suan(l,pos2) * suan(pos2+1,r);
		else return suan(l,pos2) / suan(pos2+1,r);
	}
	else if(pos3!=-1)
	{
		return pow(suan(l,pos3),suan(pos3+1,r));
	}
}

int main()
{
	cin>>a;
	int len=a.size();
	cout<<suan(0,len);
}

 上面代码前部分的字符串转换数字也可以这样

double zhuan(int l,int r)
{
	double num=0;
	int i=l;
	for(;i<r;i++)
	{
		if(a[i]!='.')
		{
			num = num*10 + a[i] - '0';
		}
		else
		{
			i++;
			break;
		}
	}
	double d=0.1;
	for(;i<r;i++)
	{
		num = num + (a[i] - '0')*d;
		d*=0.1;
	}
	return num;
}

n行四列数,随机总和为0

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

const int N = 4000;
int n, a[4][N];
 

void pre(vector<int>& p, int x, int y)
{
    int cnt = 0;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            p[++cnt] = a[x][i] + a[y][j];
        }
    }
}

int main()
{
    cin >> n;
    for(int i=0; i<n; i++)
    {
        cin >> a[0][i] >> a[1][i] >> a[2][i] >> a[3][i];
    }
    
    n *= n;
	vector<int> q(n), p(n);
	pre(p, 0, 1);
    pre(q, 2, 3);
    sort(q.begin(), q.end());

    int cnt = 0;
    
    for(int i=0; i<n; i++)
    {
        cnt += upper_bound(q.begin(), q.end(), -p[i]) - lower_bound(q.begin(), q.end(), -p[i]);
    }

    cout << cnt << endl;

    return 0;
}
  • lower_bound(q.begin(), q.end(), -p[i]):在有序序列 q 中查找第一个大于或等于 -p[i] 的元素,返回该元素的迭代器。
  • upper_bound(q.begin(), q.end(), -p[i]):在有序序列 q 中查找第一个大于 -p[i] 的元素,返回该元素的迭代器。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    int arr[] = {1, 2, 2, 3, 3, 3, 4, 5, 6, 6};
    vector<int> vec(arr, arr + sizeof(arr) / sizeof(arr[0]));

    vector<int>::iterator lower = lower_bound(vec.begin(), vec.end(), 3);
    vector<int>::iterator upper = upper_bound(vec.begin(), vec.end(), 3);

    cout << "Lower bound index: " << lower - vec.begin() << endl; // 输出 3,即第一个 3 的位置
    cout << "Upper bound index: " << upper - vec.begin() << endl; // 输出 6,即最后一个 3 的下一个位置
    cout << "Number of 3s: " << upper - lower << endl; // 输出 3,即元素 3 的个数

    return 0;
}

二分法:空教室分配

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct jiao
{
    int a,b,d;
};
int n,m;
vector<jiao> s(1000);
int r[1000],delat[1000];

bool judge(int x)
{
    for(int i=0;i<n;i++)
    {
        if(i==0)
        {
            delat[i]=r[i];
        }
        else
        {
            delat[i]=r[i]-r[i-1];
        }
    }
    for(int i=0;i<x;i++)
    {
        delat[s[i].a+1]-=s[i].d;
        delat[s[i].b+1]+=s[i].d;
    }
    int sum=0;
    for(int i=0;i<n;i++)
    {
    	sum+=delat[i];
    	if(sum<0) return 0;
	}
}

int main()
{
	cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&r[i]);
    }
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&s[i].d,&s[i].a,&s[i].b);
    }
    int l=0,r=m;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(judge(mid)) l=mid+1;
        else r=mid;
    }
    if(l==m) cout<<0;
    else cout<<"-1\n"<<l;
}

烘干机

#include <iostream>
#include<algorithm>
#include<cmath>
using namespace std;

int n, k;
int a[1000];

bool judge(int x)
{
    int cnt = 0,t=upper_bound(a,a+n,x) - a;
    for (int i = t; i < n; i++)
    {
		cnt += ceil((a[i] - x)/double(k - 1));//这里的k-1是为了节省完整一件衣服的时间 
    }
    return cnt <= x;
}

int main()
{
    cin >> n >> k;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
    sort(a,a+n);
    int l = 1, r = 2e9;
    while (l < r)
    {
        int mid = l+r >> 1;
        if (judge(mid))
            r = mid;
        else
            l = mid + 1;
    }
    cout << l;
}

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值