机房测试8.23

题解之前

咕咕咕

因为教练不在,玩去了,好几天没有更新。%%%@wans鸽掉的几天这里有(妹子)

前几天谜题实验室推出了,每天晚上就和几个同学一起准备AC这上面的题,结果奴隶战OTK就花了好久才A。(祭奠天国的战歌)

%%% 辣个男人idy002 又来了。

prob

确实被我一眼秒杀的题,我却被我的傻逼做法秒杀了。

满足条件的一定只需要2道题。(n<=5时)

本来01状态压缩一下不就完事了,但是我脑子一抽,写了如下程序:


#include<cstdio>
#include<cctype>
#include<cstring>
#define FN "prob"

const int maxn=1e5+5;

int a[maxn],d[maxn];
int b[maxn],c[maxn];

namespace Baoli {
	void one(int num) {
		memset(b,0,sizeof(b));
		bool fl=false;
		for(int i=1;i<=num;i++) {
			char ch;while(!isdigit(ch=getchar()));
			b[i]=ch-'0';
			if(!b[i]) fl=true;
		}
		if(fl) printf("YES\n");
		else printf("NO\n");
		return ;
	}

	void two(int num) {
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		int _01=0,_00=0,_10=0;
		for(int i=1;i<=num;i++) {
			char ch;
			while(!isdigit(ch=getchar()));b[i]=ch-'0';
			while(!isdigit(ch=getchar()));c[i]=ch-'0';
			if(!b[i] && c[i]) _01++;
			if(!b[i] && !c[i]) _00++;
			if(b[i] && !c[i]) _10++;
		}
		if(_00) printf("YES\n");
		else if(_01 && _10) printf("YES\n");
		else printf("NO\n");
		return ;
	}

	void three(int num) {
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		int _000=0,_001=0,_010=0,_011=0,_100=0,_101=0,_110=0;
		for(int i=1;i<=num;i++) {
				char ch;
				while(!isdigit(ch=getchar()));a[i]=ch-'0';
				while(!isdigit(ch=getchar()));b[i]=ch-'0';
				while(!isdigit(ch=getchar()));c[i]=ch-'0';
				if(!a[i] && !b[i] && !c[i]) ++_000;
				else if(!a[i] && !b[i] && c[i]) ++_001;
				else if(!a[i] && b[i] && !c[i]) ++_010;
				else if(!a[i] && b[i] && c[i]) ++_011;
				else if(a[i] && !b[i] && !c[i]) ++_100;
				else if(a[i] && !b[i] && c[i]) ++_101;
				else if(a[i] && b[i] && !c[i]) ++_110;
		}
		if(_000 || (_001 && (_010 || _100 || _110)) || (_010 && (_100 || _101)) || (_011 && _100))
			printf("YES\n");
		else printf("NO\n");
		return ;
	}
}

int main() {
	freopen(FN".in","r",stdin);
	freopen(FN".out","w",stdout);
	int T;scanf("%d",&T);
	while(T--) {
		int n,m;scanf("%d%d",&n,&m);
		if(m==1) Baoli::one(n);
		else if(m==2) Baoli::two(n);
		else if(m==3) Baoli::three(n);
		else {
			memset(a,0,sizeof(a));
			memset(b,0,sizeof(b));
			memset(c,0,sizeof(c));
			memset(d,0,sizeof(d));
			int _0000=0,_0001=0,_0010=0,_0011=0,_0100=0,_0101=0,_0110=0,_0111=0;
			int _1000=0,_1001=0,_1010=0,_1011=0,_1100=0,_1101=0,_1110=0;
			for(int i=1;i<=n;i++) {
				char ch;
				while(!isdigit(ch=getchar()));a[i]=ch-'0';
				while(!isdigit(ch=getchar()));b[i]=ch-'0';
				while(!isdigit(ch=getchar()));c[i]=ch-'0';
				while(!isdigit(ch=getchar()));d[i]=ch-'0';
				if(!a[i] && !b[i] && !c[i] && !d[i]) ++_0000;
				else if(!a[i] && !b[i] && !c[i] && d[i]) ++_0001;
				else if(!a[i] && !b[i] && c[i] && !d[i]) ++_0010;
				else if(!a[i] && !b[i] && c[i] && d[i]) ++_0011;
				else if(!a[i] && b[i] && !c[i] && !d[i]) ++_0100;
				else if(!a[i] && b[i] && !c[i] && d[i]) ++_0101;
				else if(!a[i] && b[i] && c[i] && !d[i]) ++_0110;
				else if(!a[i] && b[i] && c[i] && d[i]) ++_0111;
				else if(a[i] && !b[i] && !c[i] && !d[i]) ++_1000;
				else if(a[i] && !b[i] && !c[i] && d[i]) ++_1001;
				else if(a[i] && !b[i] && c[i] && !d[i]) ++_1010;
				else if(a[i] && !b[i] && c[i] && d[i]) ++_1011;
				else if(a[i] && b[i] && !c[i] && !d[i]) ++_1100;
				else if(a[i] && b[i] && !c[i] && d[i]) ++_1101;
				else if(a[i] && b[i] && c[i] && !d[i]) ++_1110;
			}
			if( _0000 || (_0001 && (_0010 || _0100 || _0110 || _1000 || _1010 || _1100 || _1110 ) ) ||
						 (_0010 && (_0100 || _0101 || _1000 || _1001 || _1100 || _1101 ) ) ||
						 (_0011 && (_0100 || _1000 || _1100 ) ) ||
						 (_0100 && (_1000 || _1001 || _1010 || _1011 ) ) || (_0111 && _1000) ||
						 (_0101 && (_1000 || _1010) ) || (_0110 && (_1000 || _1001) ) )
				printf("YES\n");
			else printf("NO\n");
		}
	}
	return 0;
}

清奇的做法,做法惊人的明显,std相当于简化了那些傻逼东西。
我真的不能理解,难道三点钟睡觉对考试状态影响那么大吗?
但是,这个程序一样完美AC。
(大爷还是你大爷)

std::如下

#include <bits/stdc++.h>
using namespace std;

int n, k;
int cnt[1<<4];

void yes() {
	printf("YES\n");
}
void no() {
	printf("NO\n");
}

int main() {
	freopen("prob.in", "r", stdin);
	freopen("prob.out", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &k);
		memset(cnt, 0, sizeof(cnt));
		for(int i = 1; i <= n; i++) {
			int s = 0;
			for(int j = 0; j < k; j++) {
				int v;
				scanf("%d", &v);
				if(v) s |= 1<<j;
			}
			cnt[s]++;
		}
		int U = (1<<k) - 1;
		for(int s1 = 0; s1 <= U; s1++)
			for(int s2 = 0; s2 <= U; s2++) {
				if(!cnt[s1] || !cnt[s2]) continue;
				if(!(s1 & s2)) {
					yes();
					goto NEXT;
				}
			}
		no();
NEXT:;
	}
}

pizza

贪心。
把一张张饼子看成一个个块,算一个delta,排一下序就知道哪个更适合吃哪一种饼子。
在delta正负分界的地方转换吃的饼子,中间这个块就两种都比较,哪个好吃吃哪个。

(其实是披萨)

有这么一个思路,写法千奇百怪。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

struct Stat {
	int d, s;
	Stat(){}
	Stat(int d, int s):d(d),s(s){}
};
bool operator<(const Stat &r, const Stat &s) {
	return r.d > s.d;
}

int n, S;
int s[N], a[N], b[N], d[N];
Stat stats[N];
long long pres[N];

long long cp(long long len) {
	long long ans = 0;
	for(int i = 1; i <= n; i++) {
		if(pres[i] <= len) {
			ans += (long long)stats[i].s * stats[i].d;
		} else {
			ans += (long long)(len - pres[i-1]) * stats[i].d;
			break;
		}
	}
	return ans;
}
long long calc(long long s, long long more) {
	vector<int> vc;
	for(int i = 1; i <= n; i++) {
		if(pres[i] >= s) {
			for(int j = 1; j <= pres[i] - s + 1 && more >= 1; j++) {
				vc.push_back(stats[i].d);
				more--;
			}
			for(int ii = i + 1; ii <= n && more >= 1; ii++)
				for(int j = 1; j <= stats[ii].s && more >= 1; j++) {
					vc.push_back(stats[ii].d);
					more--;
				}
			long long ans = 0;
			for(int t = 0; t < (int)vc.size(); t++) {
				if(vc[t] > 0) ans += vc[t];
			}
			return ans;
		}
	}
	return 0;
}
int main() {
	freopen("pizza.in", "r", stdin);
	freopen("pizza.out", "w", stdout);
	scanf("%d%d", &n, &S);
	long long sum = 0, ans = 0;
	for(int i = 1; i <= n; i++) {
		scanf("%d%d%d", s+i, a+i, b+i);
		sum += s[i];
		ans += (long long)b[i] * s[i];
		stats[i] = Stat(a[i] - b[i], s[i]);
	}
	sort(stats+1, stats+1+n);
	for(int i = 1; i <= n; i++) 
		pres[i] = pres[i-1] + stats[i].s;
	long long m = (sum + S - 1) / S;
	long long sub = 0;
	if(stats[n].d >= 0) {
		for(int i = 1; i <= n; i++)
			sub += (long long)stats[i].d * stats[i].s;
		ans += sub;
		printf("%lld\n", ans);
	} else {
		for(int i = 1; i <= n; i++) {
			if(stats[i].d < 0) {
				long long subans = ans + cp(pres[i-1] / S * S);
				long long more = S * m - sum;
				subans = max(subans, ans + cp(pres[i-1] / S * S + S - more) + calc(pres[i - 1] / S * S + S - more + 1, more));
				printf("%lld\n", subans);
				break;
			}
		}
	}
}

scream

我们比较容易想到的一个dp 是用dp[i][j] 前i 个数, 分成j 段, 最大的美味值. 转移为:
dp[i][j] = max dp[k -􀀀1][j - 1] + c(k,j)
然后我们发现dp[i][j] 仅由dp[i][j -􀀀 1] 转移过来, 我们把j 压掉, 然后用数据结构(线段树) 维护右边的max 值

#include <bits/stdc++.h>
using namespace std;

#define prev PREEVEV
const int N = 35000 + 10;
const int oo = 0x3f3f3f3f;

struct Node;
void modify(Node *nd, int lf, int rg, int L, int R, int delta);
struct Node {
	int vmax;
	int flag;
	Node *ls, *rs;
	void update() {
		vmax = max(ls->vmax, rs->vmax);
	}
	void pushdown(int lf, int rg) {
		if(flag) {
			int mid = (lf + rg) >> 1;
			modify(ls,lf,mid,lf,mid,flag);
			modify(rs,mid+1,rg,mid+1,rg,flag);
			flag = 0;
		}
	}
}pool[N*2], *tail, *root;

int n, m;
int aa[N], pos[N], prev[N];
int dp[2][N];
int cur = 1, prv = 0;

Node *build(int lf, int rg) {
	Node *nd = ++tail;
	nd->vmax = nd->flag = 0;
	if(lf == rg) {
		nd->vmax = dp[prv][lf];
	} else {
		int mid = (lf + rg) >> 1;
		nd->ls = build(lf, mid);
		nd->rs = build(mid+1, rg);
		nd->update();
	}
	return nd;
}
void modify(Node *nd, int lf, int rg, int L, int R, int delta) {
	if(L <= lf && rg <= R) {
		nd->vmax += delta;
		nd->flag += delta;
		return;
	}
	int mid = (lf + rg)>>1;
	nd->pushdown(lf,rg);
	if( L <= mid )
		modify(nd->ls, lf, mid, L, R, delta);
	if( R > mid )
		modify(nd->rs, mid+1, rg, L, R, delta);
	nd->update();

}
int query(Node *nd, int lf, int rg, int L, int R) {
	if(L <= lf && rg <= R)
		return nd->vmax;
	int mid = (lf + rg) >> 1;
	nd->pushdown(lf,rg);
	int rt = -oo;
	if( L <= mid )
		rt = max( rt, query(nd->ls, lf, mid, L, R) );
	if( R > mid )
		rt = max( rt, query(nd->rs,mid+1,rg,L,R) );
	return rt;
}
int main() {
	freopen("scream.in", "r", stdin);
	freopen("scream.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++)
		scanf("%d", aa + i);
	for(int i = 1; i <= n; i++) {
		prev[i] = pos[aa[i]];
		pos[aa[i]] = i;
	}
	
	for(int i = 1; i <= n; i++) 
		dp[prv][i] = dp[prv][i-1] + (prev[i] == 0);
	for(int k = 2; k <= m; k++) {
		tail = pool;
		root = build(1, n);
		for(int i = 1; i <= n; i++) {
			if(i < k )
				dp[cur][i] = -oo;
			else {
				modify(root, 1, n, max(prev[i],1), i - 1, +1);
				dp[cur][i] = query(root, 1, n, 1, i - 1);
			}
		}
		swap(prv, cur);
	}
	printf("%d\n", dp[prv][n]);
}

总结(讲垃圾话)

今天T1少写一行掉50分,充分证明晚睡觉的坏处。
T2 90分贪心就很迷。
T3 没时间写。

马上开学了,学校人越来越多,PS4完全不敢在党员工作室玩,真的难受。

明天又回家了,开学逼近,作业:1/100。
反正开学就要停课,应该没什么关系吧。

妥妥的200+就这么没了。

我的Rank3啊!

posted @ 2018-08-23 17:03  LoLiK  阅读(146)  评论(0编辑  收藏  举报