这次题目出的都是一些偏向于基础的题目,就是一些简单的模拟,思维,以及基础算法(二分,前缀和)
(点击题目标题,进入原题)
我是签到题
题解:就是说给你 t 组数据,然后每组数据输入两个,一个x,一个y,然后先输出其中的最小值,再输出其中的最大值。
cpp
#include<bits/stdc++.h>
using namespace std;
long long x,y;
int main()
{
long long t;
cin>>t;
while(t--)
{
cin>>x>>y;
printf("%lld %lld\n",min(x,y),max(x,y));
}
return 0;
}
能否形成不同的矩形
题解:能够拆开并且拼凑到一起的边一定是偶数,因此,我们就是单纯去模拟就可以了,如果是偶数就去分开,将其拼凑在一起,判断和之前的是否形成了不一样的矩形(纯粹的模拟题,题目上咋说,你去就咋做)
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int a,b;
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
int flag=0;
cin>>a>>b;
int x=0,y=0;
if(a%2==0)
{
y=2*b;
x=a/2;
if(x!=a&&y!=b&&x!=b&&y!=a)
{
flag=1;
}
}
if(b%2==0)
{
y=b/2;
x=2*a;
if(x!=a&&y!=b&&x!=b&&y!=a)
{
flag=1;
}
}
if(flag==1)
{
cout<<"YES\n";
}
else
{
cout<<"NO\n";
}
}
return 0;
}
能否形成不同的字符串
题解:这题比第二个还简单,只需要判断是否能够形成不同的字符串,首先就是你得先判断字符串里面是否有不同的字母,如果没有肯定 是NO,如果有不同的字母,输出YES,并且随机交换两个不同的字母输出就行
cpp
#include<bits/stdc++.h>
using namespace std;
string s;
int t;
int flag;
char r[5000005];
int x,y;
int main()
{
cin>>t;
while(t--)
{
flag=0;
cin>>s;
int len=s.size();
for(int i=1;i<len;i++)
{
if(s[i]!=s[i-1])
{
flag=1;
x=i,y=i-1;
}
}
for(int i=1;i<len;i++)
{
r[i-1]=s[i];
}
r[len-1]=s[0];
if(flag==0)
printf("NO\n");
else
{
printf("YES\n");
for(int i=0;i<len;i++)
{
printf("%c",r[i]);
}
printf("\n");
}
}
return 0;
}
查找
这题唯一考点就是二分查找,并且数据结构课应该讲过(我不怎么听课,我不确定,应该是讲过的)
cpp
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[1000005];
int target,l,r,mid;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&target);
l=1;r=n;
while(l<r)
{
mid=(l+r)/2;
if(a[mid]>=target)
r=mid;
else
l=mid+1;
}
if(a[l]==target)
printf("%d ",l);
else
printf("-1 ");
}
return 0;
}
A. Contest Proposal
这题就是说有n个题目,每个题目的难度为a[i],要求每个题目的难度不大于对应的b[i],每次可以添加一个题目并且删去最难的题目,求最多能添加几个题目
思路很简单,只要a[i]>b[i],那么就将a[i]改成b[i],并且重新对数组进行排序,然后继续比较就行
cpp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t;
ll n;
ll a[105];
ll b[105];
void solve(){
ll u = n;
ll sum = 0;
for(int i=n;i>=1;i--)
{
if(a[i]>b[u])
{
sum++;
}
else
{
u--;
}
}
printf("%lld\n",sum);
}
int main()
{
cin>>t;
while (t--)
{
cin>>n;
for (int i = 1; i <= n; i++)
cin>>a[i];
for (int i = 1; i <= n; i++)
cin>>b[i];
solve();
}
return 0;
}
B. Sasha and the Drawing
题解:纯思维性题目,做不出来也算正常,这题 自己在本子上画的话,会发现最多只有前n - 1给才能占两个对角线,也就是2*(n-1)个对角线,剩下的一个涂色只能占一个对角线,因此我们通过这个思路去计算即可
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
signed main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
int sum=2*n-2;
if(k<=(2*n-2)*2)
{
if(k%2==0)
cout<<k/2<<"\n";
else
cout<<k/2+1<<"\n";
}
else
{
int cnt=2*n-2;
k-=(2*n-2)*2;
cnt+=k;
cout<<cnt<<"\n";
}
}
return 0;
}
P1314 [NOIP2011 提高组] 聪明的质监员
题意:就是说给你n个矿石,然后,这n个矿石都有自己的重量w,以及其价值v,我们有一种判断机制,就是说给你m个区间范围,每次给你一个左边界L和右边界R,我们的计算机理是,这个区间内的大于规定筛选重量W的数量,乘以大于筛选重量的价值,然后将总的算出来的y累加到一起,看看和规定的标准值S最小差多少,输出最小的参数W
思路,我们发现这题数据超大,必然会有优化方法,我们通过上面·的题意可以发现,我们的参数设置的越大,能过筛选的石头越少,得到的y值越小,设置的越小,能筛选过的石头越多,得到的y值越大,因此我们可以用二分(二分的范围就是给的数据的石头的最小值到最大值,但是我们还要扩增范围,最小值减一,最大值加二)然后我们每次二分的就是参数W,然后在计算过程中要用到前缀和优化,我们要去记录出现的大于参数的矿石数目以及总价值,然后我们去计算总的Y值,Y值大于标准值S就说明,我们的参数设置的小了,要增大左边界,要是小于标准值,就说明,我们的参数设置的太大了,要缩小右边界
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,s;
int w[200005];
int v[200005];
int l[200005],r[200005];
int maxn=0;
int minn=0x3f3f3f3f3f3f3f3f;
int sumn[200005];
int sumv[200005];
int ans=0;//统计本次筛选的总价值
int mn=0x3f3f3f3f3f3f3f3f;//统计最小差值
bool check(int mid)
{
memset(sumn,0,sizeof(sumn));
memset(sumv,0,sizeof(sumv));
int ans=0;//统计总的价值也就是y[i]
for(int i=1;i<=n;i++)
{
if(w[i]>=mid)
{
sumn[i]=sumn[i-1]+1;//统计能过筛查的数量
sumv[i]=sumv[i-1]+v[i];//统计能过筛查的价值
}
else
{
sumn[i]=sumn[i-1];
sumv[i]=sumv[i-1];
}
}
for(int i=1;i<=m;i++)
{
ans+=(sumn[r[i]]-sumn[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]);
}
mn=min(mn,llabs(ans-s));
if(ans>s)
return true;
return false;
}
signed main()
{
cin>>n>>m>>s;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
maxn=max(maxn,w[i]);//二分的上下边界
minn=min(minn,w[i]);
}
int left,right,mid;
for(int i=1;i<=m;i++)
{
cin>>l[i]>>r[i];
}
left=minn-1,right=maxn+2;
while(left<=right)
{
mid=(left+right)/2;
if(check(mid))
{
left=mid+1;
}
else
{
right=mid-1;
}
}
cout<<mn;
return 0;
}