Codeforces Round #364 (Div. 2):

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guhaiteng/article/details/52005852

传送门:A. Cards  (暴力)

思路:因为每个人手里的卡片值和最后要相等,并且保证有解且卡片数为偶数,所以最后每个人手里的卡片值和必为总值除以人数,即为平均数,然后从头到尾暴力一下,如果当前数没被访问,就从它后面再找一个没被访问的数,使得它们的和为平均数,输出答案并标记它们已被访问即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int num[N];
bool vis[N];
int n;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	int sum = 0;
	for (int i=0; i<n; ++i){
		cin >> num[i];
		sum += num[i];
	}
	sum /= (n/2);
	for (int i=0; i<n; ++i)
		if (!vis[i]){
			vis[i] = true;
			for (int j=i+1; j<n; ++j)
				if (!vis[j] && num[i]+num[j]==sum){
					cout << i+1 << " " << j+1 << endl;
					vis[j] = true;
					break;
				}
		}
	return 0;
}

另外一种做法,分给每个人的肯定一大一小配对的,所以先排序一下,用pair记住原来的位置即可(当时想的这个方法,但是并没有很好的用STL实现

#include <bits/stdc++.h>
using namespace std;
int n;
vector<pair<int, int> > cards;
//-----------------------------------------------------------------
int main()
{
	scanf("%d", &n);
	for(int i=0; i<n; i++){
		int a;
		scanf("%d", &a);
		cards.push_back(make_pair(a, i + 1));
	}
	sort(cards.begin(), cards.end());

	for(int i=0; i<n/2; i++) {
		int j = n-1-i;
		printf("%d %d\n", cards[i].second, cards[j].second);
	}
}



传送门:B. Cells Not Under Attack   

题意:~

思路:只要当前一个旗子放在某一个位置,这个位置所在行列都会被攻击,那么只要统计那些行列被占据了即可。所以用两个集合维护行列被占据了几行几列(集合可以避免重复),假设行占据了x行,列占据了y列,那么当前还剩下n*n-x*n-(n-x)*y个位置,输出这个值即可。当时刚刚做的时候还傻傻的用数组。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
set<int> s1, s2;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m;
	ll t = 1LL*n*n;
	int a, b, c=0;
	while (m--){
		cin >> a >> b;
		s1.insert(a);
		s2.insert(b);
		ll ans = t-1LL*s1.size()*n-1LL*(n-s1.size())*s2.size();
		if (c)cout << " ";
		cout << ans;
		++c;
	}
	cout << endl;
	return 0;
}


传送门C. They Are Everywhere   (尺取法)


尺取法裸题,类似于POJ3320

#include <bits/stdc++.h>
#define ll __int64
using  namespace  std;
const int inf=0x3f3f3f3f;
int n;
char  s[100005];
int  a[100005];

void  solve(){
    set<int>all;
    for(int i=0; i<n; i++){
        all.insert(a[i]);
    }
    int len=all.size();
//    printf("len=%d\n",len);

    int s=0,t=0,num=0;
    map<int,int>cnt;
    int res=n;
    for(;;){
        while(t<n&&num<len){
            if(cnt[a[t++]]++==0){
                num++;
            }
        }
//        printf("s=%d t=%d\n",s,t);
        if(num<len)break;
        res=min(res,t-s);
        if(--cnt[a[s++]]==0){
            num--;
        }
    }
    printf("%d\n",res);
}

int  main(){
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
        scanf("%d",&n);
        getchar();
        for(int i=0; i<n; i++){
            scanf("%c",&s[i]);
            a[i]=s[i]-'A';
//            printf("a[%d]=%d\n",i,a[i]);
        }
        solve();

    return 0;
}

传送门:D. As Fast As Possible     (math)

题意:~

思路:对于最小时间,一定满足所有的队伍同时到达终点,也就是所有的队伍走路和坐车的时间是相同的。 

也就是说汽车运最后一组学生和第一组学生同时到达终点,这里要好好推敲一下,画图看看,就知道求的是一个数学的追及问题

最后推出的公式可以人工求解,也可以二分

CF拿初中题来考,不要被吓得不敢做。。。。

#include <bits/stdc++.h>
#define ll __int64
#define pr(x) cout << #x << "= " << x << "  "
#define pl(x) cout << #x << "= " << x << endl;
using  namespace  std;
const int inf=0x3f3f3f3f;
int n, k;
double l, v1, v2;

int  main(){
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    while (cin >> n >> l >> v1 >> v2 >> k) {
        double a = (v2 - v1) /(v2 + v1) * v1 + v1;
        double b = (k + n - 1) / k - 1;
        double t2 = l / (a * b + v2);
        double t1 = (l - v2 * t2) / v1;
        printf("%.14f\n", t1 + t2);
     }
    return 0;
}


小结:这场CF以初中题见长啊,这让大学生有些GG........

展开阅读全文

没有更多推荐了,返回首页