山西胡策 #6

A.

题意:求去掉d物品后容量为e最大背包。每个物品有三种属性,权值、容量、数量。

#include <bits/stdc++.h>
using namespace std;
const int V=1000, N=1005;
void zop(int *d, int w, int v) {
	for(int i=V; i>=v; --i) d[i]=max(d[i], d[i-v]+w);
}
void cmp(int *d, int w, int v) {
	for(int i=v; i<=V; ++i) d[i]=max(d[i], d[i-v]+w);
}
void dcp(int *d, int w, int v, int c) {
	if(c*v>=V) { cmp(d, w, v); return; }
	for(int i=1; i<=c; ++i) zop(d, w, v);
}
int l[N][V+5], r[N][V+5], a[N], b[N], c[N], n;
int main() {
	scanf("%d", &n);
	for(int i=1; i<=n; ++i) scanf("%d%d%d", &a[i], &b[i], &c[i]);
	for(int i=1; i<=n; ++i)
		memcpy(l[i], l[i-1], sizeof l[i-1]), dcp(l[i], b[i], a[i], c[i]);
	for(int i=n; i>=1; --i)
		memcpy(r[i], r[i+1], sizeof r[i+1]), dcp(r[i], b[i], a[i], c[i]);
	int q; scanf("%d", &q);
	while(q--) {
		int d, e, ans=0;
		scanf("%d%d", &d, &e); ++d;
		for(int i=0; i<=e; ++i) ans=max(ans, l[d-1][i]+r[d+1][e-i]);
		printf("%d\n", ans);
	}
	return 0;
}

考场sb没话说,只拿了80分暴力分= =

题解:背包其实是可以合并的,因此预处理前面的背包和后面的背包,查询的时候合并即可。(妈呀谁来教我多重背包怎么优化啊,二进制分组貌似并不能计算出每一个背包的值啊= =

B.

题意:对于博弈树,定义最小黑方胜集合为最小的叶子节点集合,满足集合内的叶子如果确定是胜利,那么黑方必胜。最小白方胜集合同理。现在给出博弈树,求黑方先手的情况下既在最小白方胜集合的点也在最小黑方胜集合的点。

#include <bits/stdc++.h>
using namespace std;
const int N=200005;
struct E { int next, to; }e[N<<1];
int ihead[N], cnt, n, sz[N];
void add(int x, int y) {
	e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt;
	e[++cnt]=(E){ihead[y], x}; ihead[y]=cnt;
}
int dfs1(int x, int f, bool dep=0) {
	int ret=dep?0:~0u>>1, c=1;
	for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=f) {
		c=0; int y=e[i].to;
		int s=dfs1(y, x, !dep);
		if(dep) ret+=s;
		else ret=min(ret, s);
	}
	if(c) return sz[x]=1;
	return sz[x]=ret;
}
void dfs2(int x, int f, int *ok, bool dep=0) {
	int c=1;
	for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=f) {
		c=0;
		int y=e[i].to;
		if(dep) dfs2(y, x, ok, !dep);
		else {
			if(sz[y]==sz[x]) dfs2(y, x, ok, !dep);
		}
	}
	if(c) ok[x]=1;
}
void work(int *ok, int rt) {
	dfs1(rt, -1);
	dfs2(rt, -1, ok);
}
int vis[2][N];
int main() {
	scanf("%d", &n);
	for(int i=2; i<=n; ++i) { int x; scanf("%d", &x); add(x, i); }
	work(vis[0], 1);
	add(n+1, 1);
	work(vis[1], n+1);
	int ans=0, tot=0, xo=0;
	for(int i=1; i<=n; ++i) if(vis[0][i] && vis[1][i]) { if(!ans) ans=i; tot++; xo^=i; }
	printf("%d %d %d\n", ans, tot, xo);
	return 0;
}

推了一下结论,首先根据博弈论,当前节点必胜当且仅当后继节点至少有一个必败态,必败当且仅当后继节点全为必胜态。可以发现当前节点要胜时,后继只需要一个必败态,而不可能大于两个必败态(多余两个只会增大集合)。因此按照博弈论的知识对树dfs两次就好辣。求白方必胜我们只需要新加一个节点连边黑方先手的节点就行啦。

C.

D.

题意:给出一个序列A,求一个序列B使得max{|B[i]-A[i]|}最小。

#include <bits/stdc++.h>
using namespace std;
const int N=5000005;
typedef long long ll;
int a[N], n, Sa, Sb, Sc, Sd, mo;
inline int F(int x) { x%=mo; return ((ll)Sa*x%mo*x%mo*x%mo + ((ll)Sb*x%mo*x%mo + ((ll)Sc*x%mo + Sd)%mo)%mo)%mo; }

bool check(ll d) {
	ll pre=(~0ull>>1)+1;
	for(int i=1; i<=n; ++i) {
		if((ll)a[i]>=pre) pre=max((ll)a[i]-d, pre);
		else {
			if((ll)a[i]+d<pre) return 0;
		}
	}
	return 1;
}
int main() {
	scanf("%d%d%d%d%d%d%d", &n, &Sa, &Sb, &Sc, &Sd, &a[1], &mo); Sa%=mo; Sb%=mo; Sc%=mo; Sd%=mo;
	for(int i=2; i<=n; ++i) a[i]=(F(a[i-1])+F(a[i-2]))%mo;
	ll l=0, r=(ll)(~0u>>1)*2ll;
	while(l<=r) {
		ll mid=(l+r)>>1;
		if(check(mid)) r=mid-1;
		else l=mid+1;
	}
	printf("%lld\n", r+1);
	return 0;
}

一开始看错题以为是sum= =后来发现是max。。。。。。

于是二分答案就行辣= =

然后发现题解是有一个结论= =差值最大的逆序对的差值除以二取上界= =。。。。(好像显然吧= =。。。

时间: 2024-11-07 02:18:45

山西胡策 #6的相关文章

山西胡策 #7

A. B. C. 题意:给出(i, j)之类的约束表示要j必须先i,问1尽量靠前.2尽量靠前.3尽量靠前以此类推的最优方案,或输出无解. #include <bits/stdc++.h> using namespace std; const int N=100005; int cnt, ihead[N], in[N], ans[N], tot, n, m; struct E { int next, to; }e[N]; void add(int x, int y) { e[++cnt]=(E)

弱省胡策系列简要题解

现在不是非常爽,感觉智商掉没了,就整理一下最近弱省胡策的题目吧. 其实题目质量还是很高的. 如果实在看不懂官方题解,说不定这里bb的能给您一些帮助呢? [弱省胡策]Round #0 A 20%数据,O(n4)傻逼dp. 40%数据,O(n3)傻逼dp. 100%数据,令f(x1,y1,x2,y2)表示从(x1,y1)走到(x2,y2)的路径条数.于是所有路径就是f(1,2,n?1,m)×f(2,1,n,m?1).然而两条路径可能在中间的某个点相交,我们找出最早的交点,并在这个交点互换两条路径的后

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

校内胡策(唯一一个想出来的)

2 第一题 (third.cpp/c/pas) 题目描述 小 R 最近沉迷于一个叫做 Slay.one 的游戏. 在这个游戏中,每一局有若干人参加,最终会产生一个优胜者.优胜者会获得 一个成就点. 现在小 R 已经利用某种手段得知了每场游戏有哪些人参加.假设所有人最初成 就点都是 0 ,小 R 想要知道所有游戏结束之后成就点最多的人至少有多少成就点. 校内胡策(唯一一个想出来的) 原文地址:https://www.cnblogs.com/Lance1ot/p/9445468.html

STOI补番队胡策

#1 第一轮是我出的. 比赛情况: #1 NanoApe 300 (完美AK) #2 && #3 swm_sxt / ccz  200 A.candy 这道题就是个nim游戏, 我们知道当且仅当选出的各堆糖果的异或和为0时,先手必败. 这样问题转化为从N个数中选1一些数使得他们的异或和为0的方案数. 30%,O(2^N) DFS. 假如只有询问, 那么可以直接用类似01背包的dp解决. for i = 1 ~ 1024 dp(i, x) += dp(i-1, x^w_i); dp(i, x

【弱省胡策】Round #6 String 解题报告

感觉这个题好神啊. 首先我们只管 $a = b$ 的情况,那么我们自然就可以把这个串对 $a$ 取模,然后用 KMP 求出能弄出几个其他的 B 串. 具体就是把串先倍长,然后倒过来,然后求 $Next$ 数组,然后从 $2n$ 开始沿着 $Next[]$ 跳,直到跳到 $\le n$ 的时候停止,看哪些位置被跳到了,哪些位置就是合法的. 问题是现在 $a \neq b$ 怎么办..? 我猜啊,我们可以求出限制是 $a$ 的倍数时,哪些 B 串是合法的,再求出限制是 $b$ 的倍数是,哪些是合法的

【弱省胡策】Round #7 Rectangle 解题报告

orz PoPoQQQ 的神题. 我的想法是:给每一个高度都维护一个 $01$ 序列,大概就是维护一个 $Map[i][j]$ 的矩阵,然后 $Map[i][j]$ 表示第 $i$ 根柱子的高度是否 $\ge j$. 那么怎么维护 $Map[i][j]$ 呢..? 首先我们把柱子按照高度从小到大排序,然后依次给每个高度建主席树,初始时 $Map[i][0]$ 全是 $1$,然后如果当前高度 $i$ 比某个柱子 $j$ 的高度要大了,那么就单点修改 $Map[i][j]$,然后这个就是主席树动态开

【弱省胡策】Round #5 Handle 解题报告

这个题是我出的 sb 题. 首先,我们可以得到: $$A_i = \sum_{j=i}^{n}{j\choose i}(-1)^{i+j}B_j$$ 我们先假设是对的,然后我们把这个关系带进来,有: $$B_i = \sum_{j=i}^{n}{j\choose i}A_j = \sum_{j=1}^{n}{j\choose i}\sum_{k=j}^{n}{k\choose j}(-1)^{j+k}B_k = \sum_{j=i}^{n}B_j\sum_{k=i}^{j}{j\choose k

【弱省胡策】Round #5 Construct 解题报告

这个题是传说中的 Hack 狂魔 qmqmqm 出的构造题.当然要神. 这个题的本质实际上就是构造一个图,然后使得任意两点间都有长度为 $k$ 的路径相连,然后对于任意的 $i < k$,都存在两个点使得这两个点没有长度为 $i$ 的路径相连. 我的构造方法就是: 首先给每个点连一个自环. 构造一个大小为 $n-k+1$ 的团. 然后剩下的点造成一条链并与 $n-k+1$ 号点相连. 这样的解是一组可行解. 时间复杂度 $O(n^2)$,空间复杂度 $O(1)$. 1 #include <cs