week 4

文章展示了不同问题的解决方案,包括使用双指针优化子串分值计算,用map处理多条件数据存储和查找,全排列问题的DFS及STL算法,以及数位计算和进制转换的方法。这些例子强调了在编程中如何运用高效的数据结构和算法来解决问题。
摘要由CSDN通过智能技术生成

子串分值和:双指针

! 双指针的应用!

子串分值和
  • 一开始考虑遍历:

    • 无优化:算法时间复杂度太高了

    • 遍历的算法优化: 采取区间分块&双指针&二分算法

  • 思路贡献度

    • 数字只有第一次出现的数字对子串有贡献度;

    • 去重:set:每次储存set的长度

#include<iostream>
#include<set>
using namespace std;
int main()
{
	string a;cin>>a;
	int sum=0;
	for(int i=0;i<a.size();i++)
	{
		set<int>s;
		for(int j=i;j<a.size();j++)
		{
			s.insert(a[j]);
			sum+=s.size();
		}
	}
	cout<<sum;
	return 0;
}
蒟蒻:
  • 如何储存:
    • 需要实现的操作:去重&寻找最小值&同一个物品有两个参数(set不好同时删除)->map 同时有两个参数 自动有序
#include<iostream>
#include<map>
using namespace std;
map<int,int>m1;
map<int,int>m2;
int main()
{
	int n;cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		int op;cin>>op;
		if(op==1)
		{
			int w,t;cin>>w>>t;
			if(!m1.count(w)&&!m2.count(t))
			{
				m1[w]=t;
				m2[t]=w;
			}
		}
		if(op==2)
		{
			m2.erase(m1.begin()->second);
			m1.erase(m1.begin());
		}
		else if(op==3)
		{
			m1.erase(m2.begin()->second);
			m2.erase(m2.begin());
		}
	}
	for(int i=0;i<m1.size();i++)
	{
		sum+=m1[i];
	}
	cout<<sum;
	return 0;
}
锦标赛:

思维题:

如果a[i]为有序数列 如果a[i]-a[i-1]>=k 则接下每一个都>=k 且最大的一定赢 sum++;

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int n,k;cin>>n>>k;
	int a[100005];
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	int sum=0;
	for(int i=n;i>=2;i--)
	{
		if(a[i]-a[i-1]<=k) sum++;
		else break;
	}
	cout<<sum;
	return 0;
}

循环子串

回文字符或者本身是同一个字符【思维方法】

另一种方法:暴力

#include<bits/stdc++.h>
#include<string>
using namespace std;
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		string a;cin>>a;
		string b=a+a;
		int flag=0;
		for(int len=1;len<=n;len++)
		{
			for(int i=0;i+len<=n;i++)
			{
				string s=b.substr(i,len);
				reverse(s.begin(),s.end());
				if(b.find(s)==b.npos)
				{
					flag=1;
					break;
				}
			}
			if(flag==1)
			break;
		}
		if(flag==1) cout<<"NO";
		else cout<<"YES";
		cout<<endl;
	}
	return 0;
}
A-B数对:

简化一个是通过二分算法查找& 同时简化 寻找相同个数的——upper bound lower bound

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	long long n,c;cin>>n>>c;
	long long a[200005];
	long long sum=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];	
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
	{
		int l=lower_bound(a+1,a+1+n,a[i]+c)-a;
		int r=upper_bound(a+1,a+1+n,a[i]+c)-a;
		sum+=r-l;
	}
	
	cout<<sum;
	return 0;
}c
可重排列:全排列dfs【优化:不要把相同数值的数展开】&stl 算法

dfs

#include<bits/stdc++.h>
using namespace std;
int sum=0;
vector<int>s;
unordered_map<int,int>p;
int n;
void dfs(int x)
{
	
	if(x>sum)
	{
		for(int i=0;i<s.size();i++) printf("%d ",s[i]);
		cout<<endl;
		return;
	}
	
	for(int i=1;i<=n;i++)
	{
		if(p[i]) {
			s.push_back(i);
			p[i]--;
			dfs(x+1);
			s.pop_back();
			p[i]++;
		}
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		sum+=x;
		p[i]=x;
	}
	dfs(1);
	return 0;
}

stl

#include<bits/stdc++.h>
using namespace std;
vector<int>v;
int main()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
	     int p;cin>>p;
		for(int j=1;j<=p;j++) v.push_back(i);
	}
	do{
		for(int i=0;i<v.size();i++)
		{
			cout<<v[i]<<" ";
		}
		cout<<endl;
	}while(next_permutation(v.begin(),v.end()));
	return 0;
}
数位计算:

简单思维题:!!longlong 开到unsigned 否则会超范围

#include<iostream>
using namespace std;
int main()
{
	unsigned long long n;cin>>n;
	unsigned long long sum=0;
	unsigned long long i=9;
	unsigned long long l=1;
	for(i;i<=n;i=i*10+9)
	{
		long long x=(1+i/l*l)%998244353;
		long long y=(i/l*l)%998244353;
		sum=sum+(x*y/2)%998244353;
		l*=10;
		sum%=998244353;
	}
	unsigned long long x=(1+n-i%l)%998244353;
	unsigned long long y=(n-i%l)%998244353;
	sum=sum+(x*y/2)%998244353;
	sum%=998244353;
	cout<<sum;
	return 0;
}
进制转换
  • 注意输入和输出的格式
#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n,m;cin>>n>>m;
	long long sum=0;
	for(int i=1;i<=n;i++)
	{
		int a;cin>>a;
		string b;cin>>b;
		int l=1;
		for(int j=b.size()-1;j>=0;j--)
		{
			if(b[j]>='0'&&b[j]<='9')
			sum+=(b[j]-'0')*l;
			if(b[j]>='A'&&b[j]<='Z')
			sum+=(b[j]-'A'+10)*l;
			if(b[j]>='a'&&b[j]<='z')
			sum+=(b[j]-'a'+36)*l;
			l*=a;
		}
	}
	long long l=1;
	long long k=sum;
	while(k)
	{
		l*=m;
		k/=m;
	}
	l/=m;
	while(l>=1)
	{
		if(sum/l>=10&&sum/l<36)
		cout<<(char)(sum/l-10+'A');
		else if(sum/l>=36)
		cout<<(char)(sum/l-36+'a');
		else cout<<sum/l;
		sum%=l;
		l/=m;
	}
	return 0;
}
饿饿饭饭:

相同排除掉相同个数的数字 剩下的数字数量最小的为胜利【这个串不是所有串的子串则NO 否则则YES】

#include<iostream>
using namespace std;
int main()
{
	int t;cin>>t;
	int vis[200][200];
	int n[200];
	for(int i=1;i<=t;i++)
	{
		cin>>n[i];
		for(int j=1;j<=n[i];j++)
		{
			int x;cin>>x;
			vis[i][x]=1;
		}
	}
	for(int i=1;i<=t;i++)
	{
		int l=1;
		for(int j=1;j<=t;j++)
		{
			if(i==j) continue;
			else
			{
				int flag=0;
				for(int k=1;k<=100;k++)
				{
					//如果k在i中不出现 在j中出现
					if(vis[i][k]==0&&vis[j][k]==1)
					{
						flag=1;
						break;
					}
				}
				if(flag==0)
				{
				    l=0;
					break;
				}
			}
		}
		if(l) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	
	return 0;
}
巨大的牛棚
  • 求最大的正方形: dp

    #include<iostream>
    using namespace std;
    int a[1005][1005];
    	int f[1005][1005];
    int main()
    {
    	int n,t;cin>>n>>t;
    	
    	for(int i=1;i<=t;i++)
    	{
    		int x,y;cin>>x>>y;
    		a[x][y]=1;
    	}
    	
    	int m=-1;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(!a[i][j])
    			f[i][j]=min(min(f[i][j-1],f[i-1][j]),f[i-1][j-1])+1;
    			m=max(m,f[i][j]);
    		}
    		
    	}
    
    	cout<<m;
    	return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值