## Codeforces Global Round 2

菜鸡 只会坐A题 5分钟A题做出来 ,剩下的时间一道题也没做出来 枯了!!!
开始补题

B Alyona and a Narrow Fridge

这道题不会做, 刚开始还以为次序相连只能挨着放,完了发现连样例都过不了。完了后看tutorial 别人的代码,发现是用的贪心+二分。
1-n,n个瓶子 ,把前k个瓶子 从低到高排序,每相邻两个为一行,每行高度按照高的那个算,总高度就是:
h2+h4+h6+++ 一直加下去。
从1枚举到k 肯定是会超时的 ,所以二分的来做。
取 mid =(l+r+1 )/2,
如果l–midd所需高度高于m,则取r=mid-1
如果低于等于m 取l=mid
直到l>=r 结束循环,此时l即是答案。

#include<stdio.h>
#include<algorithm>
using namespace std;

int main(){
	int a[10000],b[10000];
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	int l=1,r=n;
	while(l<r){
		int mid=(l+r+1)>>1;
		long long temp=0;
		for(int i=1;i<=mid;i++)//辅助数组b[] 存放 a[1]-a[mid]的元素
		b[i]=a[i];
		sort(b+1,b+1+mid);//从小到大排序
		if(mid&1){//如果l到mid的元素个数为奇数,则b[1]单独计算 b[2]-b[mid] 两个一组,选大的那个相加
			temp=b[1];
			for(int i=3;i<=mid;i+=2) 
			temp+=b[i];
		}
		else
		for(int i=2;i<=mid;i+=2)//偶数个 正好
		temp+=b[i];
		
		if(temp<=m)  //k比mid大 ,下一次运算的是 l ——  (r-mid)/2这个范围
		l=mid;
		else
		r=mid-1;		//mid大于 k的值  下次取更小的区间
	}
	printf("%d\n",l);
	return 0;
}

C. Ramesses and Corner Inversion

两个n*m矩阵,都是0,1组成。
每次操作对矩阵内的某个矩阵子集 的四个角取反,即0,1取反。能否在有限个操作内把A矩阵变得和B矩阵一样。
刚开始想这道题第三题,不用写搜索,我也写不出来。。。
应该是思维题,找规律的,想了想 是两个矩阵不一样的元素的个数为偶数,代码写出来,还是错了。
应该是每一行每一列的不同元素个数都必须为偶数,才可以相互转换。
这个证明:
当这一行为奇数的时候,无论怎么转换,总会剩下一个点,每转换一次则会把另外一个点反过来,
可以说是无解。
当这一行不同元素个数为偶数的时候,总是可以通过转换把他们移动到整个矩形的边上。
We will prove this constructing a sequence of operations that transforms A to B whenever parities in all rows and column match. Let’s perform an operation (1,1,x,y) for all such x>1 and y>1 that Axy≠Bxy. After all these operations the whole matrices except maybe the first column and the first row match. But the first column and the first row also match because of the parity! So A is now B

#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,a[501][501],b[501][501],r[501],c[501];
int main()
{
	scanf("%d %d",&n,&m);
	  for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++)
	    scanf("%d",&a[i][j]);
	  for (int i=1;i<=n;i++)
	  for (int j=1;j<=m;j++)
	  {
	    scanf("%d",&b[i][j]);
	    if (a[i][j]^b[i][j]) r[i]++,c[j]++;//异或,相异为1 r[i]是i行不相同元素的个数 c[j]是 第J列
	  }
	for (int i=1;i<=max(n,m);i++)
	{
		if (r[i]%2 || c[i]%2) {printf("NO\n");return 0;}
	}
	printf("YES\n");
	return 0;
}

D. Frets On Fire

这道题理解错题意了,卡了一天,一直搞不懂为什么差分解决。
刚刚仔细看了看题里给的图,结合图才明白了题意。
大概就是
(序列可以理解为每个数列无限长,公差为一,只是起点不同)
d[i]=s[i]-s[i-1] 前后两个序列的差值,这个序列的某一段一定在r-l范围内,但pitch可能和其他的重复。
将s[]按起点从小到大排序。
求出他们的差分数组,再将差分数组 从小到大排序。
如果s[i]-s[i-1]即d[i]小于r-l(区间长度)则他和上一段有一部分重合,没重合的也就是d[i].
如果大于区间长度,则 没有任何重合,直接加上区间长度。
求出差分数组的前缀和数组sum[]。
二分的找到差分数组中比区间长度大的第一个位置i
则sum[i-1]即是所有差值小于区间长度的和。
再加上 (n-i)*(r-l+1)
再加上第一段的r-l+1
就是最终长度。

多次查询,n的话会超时,二分直接用upper_bound 函数就好。

#include<stdio.h>
#include<algorithm>
using namespace std;
	long long s[100001],d[100001],sum[100001];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%I64d",&s[i]);
	sort(s+1,s+n+1);
	for(int i=1;i<n;i++)
	d[i]=s[i+1]-s[i];
	sort(d+1,d+n);
	for(int i=1;i<n;i++)
	sum[i]+=sum[i-1]+d[i];
	int q;
	scanf("%d",&q);
	while(q--){
		long long l,r;
		scanf("%I64d %I64d",&l,&r);
		int f;
		f=upper_bound(d+1,d+n,r-l+1)-d;
		long long result=r-l+1;
		result+=sum[f-1];
		result+=(r-l+1)*(n-f);
		printf("%I64d\n",result);
	}
	return 0;
}

E题留着,过两天补

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值