2015-2016 Northwestern European Regional Contest (NWERC 2015)

A

题意:给出n,m,然后给出n个人到达的时间以及这个人在实验室所待的时间,实验室有无穷个房间,一般情况下某个房间的人离开后会直接锁房,但是Penelope很懒,不想开锁,所以她可以告诉某个人不锁房,以便下一个人来使用,但是在某个房间的人离开后m分钟房门会自动锁住,求Penelope最多可以节省几次开锁的次数

思路:排序一下,然后用优先队列维护一下右端点的值,每次来人就判断一下

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 3e5 + 10;
const LL INF = 1e9 + 10;
struct Node{
	LL s, e;
}a[qq];
bool cmp(const Node &x,const Node &y) {
	if(x.s==y.s) return x.e<y.e;
	return x.s<y.s;
}
priority_queue<LL, vector<LL>, greater<LL> > Q;
int main(){
	int n;
	LL l,m;
	scanf("%d%lld",&n,&m);
	for(int i=0;i<n;i++) {
		scanf("%lld%lld",&a[i].s,&l);
		a[i].e=a[i].s+l-1;
	}
	sort(a, a+n, cmp);
	int ans = 0;
	for(int i = 0; i < n; ++i) {
		if(Q.empty()) {
			Q.push(a[i].e);
		} else {
			while(!Q.empty()) {
				LL u = Q.top();
				if(u + m + 1 < a[i].s) {
					Q.pop();
				} else {
					if(u < a[i].s) {
						Q.pop();
						ans++;
						Q.push(a[i].e);
						break;
					} else {
						Q.push(a[i].e);
						break;
					}
				}
			}
			if(Q.empty()) {
				Q.push(a[i].e);
			}
		}
	}
	printf("%d\n", ans);
	return 0;
}


E

二分匹配裸题

注意细节就好

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2500 + 10;
const LL INF = 1e9 + 10;
vector<int> G[qq];
LL result[qq * 3];
int cnt = 0, tot = 0, n;
map<LL, int> mp;
bool vis[qq * 3];
int match[qq * 3], remt[qq * 3];
LL ta[qq], tb[qq];

int Getid(LL x) {
	if(mp[x])	return mp[x];
	mp[x] = ++cnt;
	result[cnt] = x;
	return cnt;
}
bool Dfs(int u) {
	int sz = G[u].size();
	for(int i = 0; i < sz; ++i) {
		int v = G[u][i];
		if(vis[v])	continue;
		vis[v] = true;
		if(match[v] == -1 || Dfs(match[v])) {
			match[v] = u;
			remt[u] = v;
			return true;
		}
	}
	return false;
}

int main(){
	scanf("%d", &n);
	LL a, b;
	for(int i = 1; i <= n; ++i) {
		scanf("%lld%lld", &a, &b);
		ta[i] = a, tb[i] = b;
		int idx = i;
		int idy = Getid(a + b);
		G[idx].pb(idy);
		idy = Getid(a - b);
		G[idx].pb(idy);
		idy = Getid(a * b);
		G[idx].pb(idy);
	}
	int ans = 0;
	mst(match, -1);
	for(int i = 1; i <= n; ++i) {
		mst(vis, false);
		if(Dfs(i))	ans++;
	}
	if(ans < n) {
		puts("impossible");
	} else {
		for(int i = 1; i <= n; ++i) {
			int idy = remt[i];
			LL f = result[idy];
			if(ta[i] + tb[i] == f) {
				printf("%lld + %lld = %lld\n", ta[i], tb[i], f);
			} else if(ta[i] - tb[i] == f) {
				printf("%lld - %lld = %lld\n", ta[i], tb[i], f);
			} else if(ta[i] * tb[i] ==  f) {
				printf("%lld * %lld = %lld\n", ta[i], tb[i], f);
			}
		}
	}
	return 0;
}




G

题意:有三个人去评选n只骆驼的速度,i,j表示第i个人认为第j只骆驼的速度排名,每次选出两只骆驼求有多少对骆驼满足三个人认为某一个骆驼比另外一只骆驼跑的快

思路:这题思路可以参考这个题 黑猫传送门

我们讨论三个人中任意两个人可知结果就四种情况、

假设三次比较都选出的骆驼i,j

第一种:三次比较中第i只骆驼比第j只快

第二种:两场i比j快,一场i比j慢

第三种:两场i比j慢,一场i比j快

第四种:三次比较中第i只骆驼比第j只慢

可知我们把中间两种情况排除那么剩下的情况就是我们需要的了

可知我们求出三次比较的逆序数/2就是我们需要剔除的答案了

因为第二种和第三种情况无聊怎么算最后结果都会加2,但其实是同一种

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)   memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
int a[qq], b[qq], c[qq], p[qq];
LL sum[qq];
LL GetSum(int x) {
    LL ans = 0;
    while(x > 0) {
        ans += sum[x];
        x -= x & (-x);
    }
    return ans;
}
void UpDate(int x, int n) {
    while(x <= n) {
        sum[x] += 1;
        x += x & (-x);
    }
}
LL Solve(int *t1, int *t2, int n) {
    LL ans = 0;
    for(int i = 1; i <= n; i++) {
        p[t1[i]]=i;
        sum[i]=0;
    }
    for(int i = n; i >= 1; --i) {
        ans += GetSum(p[t2[i]]);
        UpDate(p[t2[i]], n);
    }
    return ans;
}

int main(){
    int n;  scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", a + i);
    }
    for(int i = 1; i <= n; ++i) {
        scanf("%d", b + i);
    }
    for(int i = 1; i <= n; ++i) {
        scanf("%d", c + i);
    }
    LL ans = (LL)n * (n - 1);
    ans -= Solve(a, b, n) + Solve(a, c, n) + Solve(b, c, n);
//    printf("%lld\n", ans);
    printf("%lld\n", ans/2);
    return 0;
}


I

队友写的

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const LL INF = 1e9 + 10;
char s[35];
int main(){
	scanf("%s",s);
	int len=strlen(s);
	int x,y;
	if(s[0]=='0') x=1,y=1;
	else if(s[0]=='1') x=2,y=1;
	else if(s[0]=='2') x=1,y=2;
	else if(s[0]=='3') x=2,y=2;
	for(int i=1;i<len;i++) {
		x*=2;
		y*=2;
		if(s[i]=='0') x--,y--;
		else if(s[i]=='1') y--;
		else if(s[i]=='2') x--;
	}
	printf("%d %d %d\n",len,x-1,y-1);
	return 0;
}


J

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 5e5 + 10;
const LL INF = 1e9 + 10;
int n;

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i) {
		if(i != 1)	printf(" ");
		int x;	scanf("%d", &x);
		for(int j = 0; j < (1 << 8); ++j) {
			int y = (j ^ (j << 1));
			if(y >= 256)	y -= 256;
			if(y == x) {
				printf("%d", j);
				break;
			}
		}
	}
	puts("");
	return 0;
}


K

这题就是题意读懂就好了

题意:给出r,s,m,d,n,代表就r中食材,s种开胃菜,m中主菜,d种甜点以及n中禁忌,现在你要在做三道菜,开胃菜一道,主菜一道,甜点一道,问你有多少种选发,禁忌给出的是两个数,代表第i道菜和第j道菜不能在一起。r种食材又有许多品牌,第二行给的数字是r中食材包含的品牌,品牌不同所做出来的菜不同,但是如果某两道或者三道菜包含同一种食材,必定选择相同品牌,如果选发超过1e18,输出too many

好了题意我帮你们读完了可以写了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <bitset>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9;
const int qq = 1005 + 10;
const LL INF = 1e9 + 10;
const LL boundary = 1e18;
LL num[qq];
map<pill, bool> mp;
int r, s, m, d, n;
LL S[30][qq], M[30][qq], D[30][qq];
LL vis[1005];
set<int> st;

int main() {
	scanf("%d%d%d%d%d", &r, &s, &m, &d, &n);
	for(int i = 1; i <= r; ++i) {
		scanf("%lld", num + i);
	}
	for(int i = 1; i <= s; ++i) {
		int k;	scanf("%d", &k);
		S[i][0] = k;
		for(int j = 1; j <= k; ++j) {
			scanf("%lld", &S[i][j]);
		}
	}
	for(int i = 1; i <= m; ++i) {
		int k;	scanf("%d", &k);
		M[i][0] = k;
		for(int j = 1; j <= k; ++j) {
			scanf("%lld", &M[i][j]);
		}
	}
	for(int i = 1; i <= d; ++i) {
		int k;	scanf("%d", &k);
		D[i][0] = k;
		for(int j = 1; j <= k; ++j) {
			scanf("%lld", &D[i][j]);
		}
	}
	for(int a, b, i = 1; i <= n; ++i) {
		scanf("%d%d", &a, &b);
		if(a > b)	swap(a, b);
		mp[mk(a, b)] = true;
	}
	LL ans1 = 0;
	long double ans2 = 0;
	map<int, LL>::iterator it;
	bool flag = false;
	for(int i = 1; i <= s; ++i) {
		for(int j = 1; j <= m; ++j) {
			if(mp[mk(i, s + j)])	continue;
			for(int k = 1; k <= d; ++k) {
				if(mp[mk(s + j, s + m + k)])	continue;
				if(mp[mk(i, s + m + k)])	continue;
				for(int l = 1; l <= S[i][0]; ++l) {
					st.insert(S[i][l]);
				}
				for(int l = 1; l <= M[j][0]; ++l) {
					st.insert(M[j][l]);
				}
				for(int l = 1; l <= D[k][0]; ++l) {
					st.insert(D[k][l]);
				}
				LL tmp1 = 1;
				long double tmp2 = 1;
				for(set<int>::iterator it = st.begin(); it != st.end(); ++it) {
					tmp1 *= num[*it];
					tmp2 *= num[*it];
					if(tmp2 > boundary)	flag = true;
				}
				ans1 += tmp1;
				ans2 += tmp2;
				if(ans2 > boundary)	flag = true;
				st.clear();
			}
			if(flag)	break;
		}
		if(flag)	break;
	}
	if(flag) {
		puts("too many");
	} else {
		printf("%lld\n", ans1);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值