Codeforces Round 966 (Div. 3) CDE题

C. Numeric String Template

题目链接

唉,人生无常,大肠包小肠。

做两个map哈希表,一个map是int对于char的还有一个是char对到int。这两个用来意义对应对应的值,比如第一个值是2第一个对应的字符是c,那么map【2】对应的就是c,如果后面还有2对应的字符,如果对不上就NO了,另外同理。注意的是两方都要来一遍,不然可能会漏人,然后遇到是0的值的,记得修改成最大数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+10;
int n,m;
int a[N];
void solve()
{
	cin>>n;
	for(int i=0;i<n;i++){cin>>a[i];}
	cin>>m;
	while(m--)
	{
		string s;
		cin>>s;
		if(n!=s.size()){cout<<"NO"<<endl;continue;}
		map<int,char>m1;
		map<char,int>m2;
		bool jud=1;
		for(int i=0;i<n;i++)
		{
			if(a[i]==0){a[i]=1e9+10;}//此处需要大于a[i]的范围
			if(m1[a[i]]==0&&m2[s[i]]==0){m1[a[i]]=s[i];m2[s[i]]=a[i];}//此处必须两者都等于0,不然会出现匹配不上的现象,可能一个是第一次配,而对面的是之前已经配国的,如果补同时等于0,会重新赋值。
			if(m1[a[i]]!=s[i]){jud=0;}
			if(m2[s[i]]!=a[i])jud=0;
		}
		if(!jud)cout<<"NO"<<endl;
		else cout<<"YES"<<endl;
	}
	
	return ;
}
int main(){    
    int t;cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

D. Right Left Wrong

题目链接

c艹,。。。服了,比B简单多了,先求前缀和,然后从最外层王里面依次找每一对l和r,然后每一次找到一组就ans加上,注意开ll。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+10;
void solve()
{
	int n;
	cin>>n;vector<ll>ps(n+1,0);
	int a[n+10],flag=0;
	for(int i=1;i<=n;i++){cin>>a[i];ps[i]=ps[i-1]+a[i];}
	string s;cin>>s;s=' '+s;
	int p1=1,p2=n,q1=1,q2=0;ll ans=0;
	for(int i=1;i<=n;i++)
	{
		if(s[p1]=='L'&&flag==0){q1=p1;flag=1;p1++;}
		else if(flag==0)p1++;
		if(s[p2]=='R'&&flag)
		{q2=p2;flag=0;p2--;if(q2>=q1)ans+=ps[q2]-ps[q1-1];}
		else if(flag) p2--;
	}
	cout<<ans<<endl;
	return ;
}
int main(){    
    int t;cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

E. Photoshoot for Gorillas

题目链接

确实有点难度,赛时应该真写不太出来。      

​
for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int lx=max(0,i-k);
			int rx=min(n-k+1,i);
			int ly=max(0,j-k);
			int ry=min(m-k+1,j);
			b.push_back((rx-lx)*(ry-ly));
		}
	}

​

核心代码如上

核心思想是想一个边长是k的正方形动态的在动,然后看左上角,分两部分看待,首先是横着的x轴,左边可以达到i-k,但是可能超过0,所以加一个max,然后右边可以达到i,但是可能会超左边界,即要求这个要最小是n-k,同理竖着的y方向,然后把同轴相减,不同的相乘然后放容器里。最后把身高和这个容器都sort,相乘即可。难点在于推断和边界的判断,从1开始还是从0开始会产生不同推断的式子,例如如果反而for(i=0....)for(j=0...)这样推断的话,式子就需要变成:

max(0,i-k+1),min(i,n-k),最后相乘的时候也需要b.push_back((rx-lx+1)*(ry-ly+1));

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+10;
bool cmp(int a,int b)
{
	return a>b;
}
void solve()
{
	int n,m,k;cin>>n>>m>>k;
	int w;cin>>w;vector<ll>a(w+1);vector<ll>b;
	for(int i=1;i<=w;i++)cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int lx=max(0,i-k);
			int rx=min(n-k+1,i);
			int ly=max(0,j-k);
			int ry=min(m-k+1,j);
			b.push_back((rx-lx)*(ry-ly));
		}
	}
	ll ans=0;
	sort(a.begin(),a.end(),cmp);
	sort(b.begin(),b.end(),cmp);
	for(int i=0;i<w;i++)
	{
		ans+=a[i]*b[i];
		//cout<<a[i]<<" "<<b[i]<<endl;
	}
	cout<<ans<<endl;
	return ;
}
int main(){    
    int t;cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值