ABC 378 ABC

前言

人在极度无语的情况下是会笑出来的。

——灰喜鹊Cyanopica


A. Pairing

给定4个球,球可能是1、2、3、4这四种颜色中的一种。现在让你把球拿走,但你得拿相同颜色的球,而且最少得拿走两个球。请问最多能拿几次?

分析一下。

在这里借鉴一下tourist的思路(游客你带我走吧~你带我走吧~),先把四个代表颜色的数字输入到数列里,然后把它们排序。这样,相同的数会紧挨着。那么就可以比较方便地判断情况:

实际情况推导思路推导情况结果
四个值都相等没啥,就是0=1=2=3

a[0] == a[1] &&

a[1] == a[2] &&

a[2] == a[3]

cnt = 1

三个值相等

并非四个都相等时,分为前三个或者后三个相等的情况,但都会在同一次被拿走;所以只要判断有0=1或者2=3就成,1=2是必然的,不用管

a[0] == a[1] ||

a[2] == a[3]

cnt = 1
两个值相等并非四个都相等时,两对两个值相等,0=1以及2=3而且1!=2

a[0] == a[1] &&

a[2] == a[3] &&

a[1] != a[2]

cnt = 2
并非四个都相等时,只有两个值相等,分为三种情况:0=1,1=2,2=3

a[0] == a[1] ||

a[1] == a[2] || a[2] == a[3]

cnt = 1

 后面的情况都与第一种情况冲突,所以第一种情况写if,后边写else。不难注意到第二个情况和第四个情况其实可以合并(a[1] == a[2]的或条件对第二个情况来说有没有都一样),所以可以拿它俩写else if。剩下的那个情况写else。

代码如下——

int a[4] = {-1};
for (int i = 0; i < 4; i ++)
{
	cin >> a[i];
}
sort(a, a+4);

int rmb = 0;	int cnt = 0;
if (a[0] == a[1] && a[1] == a[2] && a[2] == a[3])
	cnt = 1;
else if (a[0] == a[1] && a[2] == a[3] && a[1] != a[2])
	cnt = 2;
else
{
	if (a[0] == a[1] || a[1] == a[2] || a[2] == a[3])
		cnt = 1;
	else;    //写这个else是个人习惯问题
}

做题教训&&笑点解析

布什戈门你打个比赛都不用草稿纸的吗啊?真当自己最强大脑?遇见需要分类讨论或者找边界等等需要细节的地方时,甭管容易还是困难都给我沉下心来分析打演草!

要不然就会出现卡某个测试点的情况——没思考周全。

B. Garbage Collection

我没开出来B,原因很简单,没读懂题……

题意是:

在A市,垃圾分类成N种,N大于等于1小于等于100。
第1行被用来输入N,第i种垃圾的回收方式写在第i+1行,方式是——某天的日期模除以给定的q时,刚好余数是给定的r,那么这个某天就是这种垃圾的回收日。r和q大于等于0小于等于1e9。
再给你一个Q大于等于1小于等于100,设现在有Q份垃圾,对于第t种垃圾(当然t大于等于1小于等于N),问你在给定的第d天之后的第几天才能扔,这个d大于等于0小于等于1e9。

难吗?不好理解是吗?那我们换一个说法。

按照A市的垃圾分类方法可以分出N种垃圾,其中N大于等于1小于等于100。
第i种垃圾的回收方式写在第i+1行(第1行被用来输入N),方式是——已知某一次收垃圾的日子是第r天,再过q天后垃圾车才会再来一趟。r和q很不合常理地大于等于0小于等于1e9。
现在我有Q份垃圾得扔,Q大于等于1小于等于100。
在第d天的时候我想扔第t种垃圾;这个d大于等于0小于等于1e9,t大于等于1小于等于N。现在问你,从第d天开始算,之后最近的扔垃圾的日子是第几天。

因为我们只是已知有这么一个第r天,它不一定比后来给定的第d天来的要早,也有可能比第d天来得晚,要是后者就不用非得等第r天后下一趟垃圾车什么时候来了,而是可以直接等到第r天。

我在重做这道题的时候想用tuple去做,结果发现人家数据是分段给的,没法做好像。没办法,只能含泪抄袭一下zyc老师的答案。

typedef long long ll;
const ll N=200005;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll n , q;
ll num[N][2];

void solve(){
    cin >> n;
    for (ll i = 1; i <= n; i++){
        cin >> num[i][0] >> num[i][1];
        //写进两种数组里,[i][0]是q,[i][1]是r
    }
    cin >> q;
    while(q--){
        ll a , b;
        cin >> a >> b;    //a是t,b是d
        ll c = b % num[a][0];
        //把r加上好几个q加到让r'大于d,跟把d减去好几个q从而使d'小于r的效果是等价的。
        //c就是减去好几个q之后剩下的比q小的值,也就是d'。
        if(c <= num[a][1]){
            cout << b + num[a][1] - c<< '\n';
            //c比r小,说明这个d'离下一个r不远。
            //打印b+r-c,r-c就是d'距离下一个r的距离。
            //等于就更不必说了。
        }
        else {
            cout << b + num[a][1] + num[a][0] - c << '\n';
            //c比r大,说明这个d'有点超,刚刚巧了,垃圾车前两天刚走,得等下下一个r。
            //打印b+q+r-c,q就是多等的那一个循环。
        }
    }
}

signed main(){  
    ll t = 1; //cin >> t;
    while (t--) solve();
    return 0;
}

做题教训&&笑点解析

就怎么说呢……思维要活,画画图,用用草纸。画个示意图对我来说挺有用的。

下次看不明白英文跟机翻要不直接看日文吧(

C. Repeating

给定N个正整数,N大于等于1小于2e5,正整数们大于等于1小于等于1e9。
按给定顺序输出这些数;求某一个数出现时,这串按特定顺序排序的数里面,前一个和它大小相等的数的位置。如果是第一次出现,那么位置定为-1。

分析一下。

就是对输入的数列进行循环查找,查找到了某个数b对应的前一个数a的位置就输出,然后把这个数b看作下一个可能存在的数c所对应的前一个数,参与下一轮循环。

可是这个数组不可能开得这么大,用vector还超时严重,不如用map。

map里面绑定两种数值,前一个是某个数字的数值,用来充当key;后一个是这个数字对应的位置,用来充当value(可以想一下这个key和value的选取,这个思维很重要)。

map本来就可以当数组,只不过是一个一个一个地登记式输入——先存入temp缓存,再判断这个temp之前有没有存在过,即map[temp]的值是否不为0。如果不为0,那就把它对应的那个值,也就是前一个与它相等的数的位置,给打印出来,再改成现在这个新数所在的位置,以供下次使用;如果为零,就打印-1,再改成现在这个新数所在的位置,以供下次使用。

这样就不至于真的要存10,0000,0000个数了,只需要存出现过的那几类数就好了,而且重复出现时,把value一改就完事,能占一个位置就绝对不占两个位置。这样你看,空间也节省了,时间也节省了,多好。

代码如下——

map<int, int> m;	int n = 0;

cin >> n;	int temp = 0;
for (int i = 1; i <= n; i ++)
{
	cin >> temp;
	if (m[temp] != 0)	cout << m[temp] <<" ";
	else
		cout << "-1 ";
	m[temp] = i;    //简化一下,既然都得存新位置,那就放if/else后面就行
}

//感谢gzx老师,我爱西红柿

做题教训&&笑点解析

人不能在一块石头上跌倒两次,你这都第几次了?啊?事不过三!map!学会用好map!憋老惦记着你那破数组了!

另外这个map反过来“先有数值再找位置”的思想确实是跟数组“先有位置再找数值”不一样。我不知道这种思维怎么练,但是我知道我得先积累着。

小结

D题得要dfs……天哪我连树都没搞懂你让我搞这个……任重而道远啊……

感觉打这个ACM能每天给我过个sancheck,过几天说不定我就能在现实生活中看见爱慕织姬了嘿嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值