CSPJ简易题解

T1

显然的二进制拆分。

由于闲的没事干所以写了个栈(

采用树状数组那样的 lowbit 写法求出每一个 \(1\)

代码:

#if 0
长春这天下大雨,武昌这天下大雨。
连续两天下大雨,持续两天下大雨。
东京前天下大雨,龙华前天下大雨。
显然今天下大雨,勿忘今天下大雨。
双人飞天下大雨,泪雨滂沱下大雨。
我也想他下大雨,直接让他下大雨。
德州后天下大雨,虽然昨天下大雨。
六月份天下大雨,后五月天下大雨。 
#endif
#include<bits/stdc++.h>
using namespace std;
int read(){
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar()))x=x*10+(ch^'0');
	return x;
}
int main(){
	freopen("power.in","r",stdin);
	freopen("power.out","w",stdout);
	int n=read();
	if(n&1)puts("-1");
	else{
		stack<int>tmp;
		while(n)tmp.push(n&-n),n&=n-1;
		while(!tmp.empty())printf("%d ",tmp.top()),tmp.pop();
	}fflush(stdout);
	return 0;
}

T2

显然的维护值域计数器。

由于闲着没事干莽了个线段树。

代码:

#if 0
长春这天下大雨,武昌这天下大雨。
连续两天下大雨,持续两天下大雨。
东京前天下大雨,龙华前天下大雨。
显然今天下大雨,勿忘今天下大雨。
双人飞天下大雨,泪雨滂沱下大雨。
我也想他下大雨,直接让他下大雨。
德州后天下大雨,虽然昨天下大雨。
六月份天下大雨,后五月天下大雨。 
#endif
#include<bits/stdc++.h>
using namespace std;
int read(){
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar()))x=x*10+(ch^'0');
	return x;
}
const int N=609,M=1024;
int zkw[N<<2];
inline void update(int x){
	for(++zkw[x+=M];x>>=1;zkw[x]=zkw[x<<1]+zkw[x<<1|1]);
}
inline int query(int num){
	register int pos=1;
	while(pos<M){
		if(zkw[pos<<1]>=num)pos<<=1;
		else num-=zkw[pos<<1],pos=pos<<1|1;
	}return pos-M;
}
int main(){
	freopen("live.in","r",stdin);
	freopen("live.out","w",stdout);
	register int n=read(),w=read();
	for(register int i=1;i<=n;++i){
		update(601-read());
		printf("%d ",601-query(max(i*w/100,1)));
	}fflush(stdout);
	return 0;
}

T3

有点小难度。

思路:维护表达式树(<-初赛内容)。

解析字符串建表达式树部分略。

先处理 not,在节点上打标记,然后先根遍历下放,途中 andor 互换,\(0\)\(1\) 也互换。

然后后根遍历求出每个点对应的表达式子树的值。

然后先根遍历,遍历到一个点的时候,如果这个点的父亲和兄弟使得表达式计算到这里时出现了和 \(0\) and 或者和 \(1\) or 就代表这个点被废弃了(无用),打个标记。

然后先根遍历下传标记。

最后改变一个点的值的时候,如果这个点有废弃标记,那肯定没影响。

反之,则一定一路都是和 \(1\) and 或者和 \(0\) or,自然答案也会改变。

代码:

#if 0
长春这天下大雨,武昌这天下大雨。
连续两天下大雨,持续两天下大雨。
东京前天下大雨,龙华前天下大雨。
显然今天下大雨,勿忘今天下大雨。
双人飞天下大雨,泪雨滂沱下大雨。
我也想他下大雨,直接让他下大雨。
德州后天下大雨,虽然昨天下大雨。
六月份天下大雨,后五月天下大雨。 
#endif
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
int fa[N],tot;
int lson[N],rson[N];
bool val[N];
int fst[N];
char op[N];
bool tag[N];
char f[N],*p=f;
bool abded[N];
stack<int>stk;
int read_on_str(){
	#define getchar() *(p++)
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar()))x=x*10+(ch^'0');
	--p;
	return x;
}
void Pr_str(){
	gets(f);
	while(*p){
		while(*p==' ')++p;
		if(*p=='x'){
			fst[read_on_str()]=++tot;
			stk.push(tot);
		}else if(*p=='&'||*p=='|'){
			op[++tot]=*(p++);
			register int u=stk.top();stk.pop();
			fa[u]=tot,lson[tot]=u;
			u=stk.top();stk.pop();
			fa[u]=tot,rson[tot]=u;
			stk.push(tot);
		}else{
			++p;
			register int u=stk.top();
			tag[u]^=1;
		}
	}
}
#undef getchar
int read(){
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar()))x=x*10+(ch^'0');
	return x;
}
int main(){
	freopen("expr.in","r",stdin);
	freopen("expr.out","w",stdout);
	Pr_str();
	register int n=read();
	for(register int i=1;i<=n;++i)val[fst[i]]=read();
	for(register int i=tot;i;--i)if(tag[i]){
		tag[lson[i]]^=1,tag[rson[i]]^=1;
		if(op[i]=='|')op[i]='&';
		else if(op[i]=='&')op[i]='|';
		else val[i]^=1;
	}	
	for(register int i=1;i<=tot;++i){
		if(op[i]=='|'){
			if(val[lson[i]])abded[rson[i]]=true;
			if(val[rson[i]])abded[lson[i]]=true;
			val[i]=val[lson[i]]|val[rson[i]];
		}
		else if(op[i]=='&'){
			if(!val[lson[i]])abded[rson[i]]=true;
			if(!val[rson[i]])abded[lson[i]]=true;
			val[i]=val[lson[i]]&val[rson[i]];
		}
	}
	for(register int i=tot;i;--i)if(abded[i])abded[lson[i]]=abded[rson[i]]=true;
	register char ret=val[tot]^'0';
	for(register int q=read();q;--q){
		putchar(ret^!abded[fst[read()]]),putchar('\n');
	}fflush(stdout);
	return 0;
}

T4

显然的 dp,状态为当前坐标和上一次从哪里走来。

瞎转移即可,见代码。

#if 0
长春这天下大雨,武昌这天下大雨。
连续两天下大雨,持续两天下大雨。
东京前天下大雨,龙华前天下大雨。
显然今天下大雨,勿忘今天下大雨。
双人飞天下大雨,泪雨滂沱下大雨。
我也想他下大雨,直接让他下大雨。
德州后天下大雨,虽然昨天下大雨。
六月份天下大雨,后五月天下大雨。 
#endif
#include<bits/stdc++.h>
using namespace std;
int read(){
	register char ch;
	register bool f=false;
	while(!isdigit(ch=getchar()))if(ch=='-')f=true;
	register int x=ch^'0';
	while(isdigit(ch=getchar()))x=x*10+(ch^'0');
	return f?-x:x;
}
long long dp[3][1009][1009];
//0:从左;1:从下;2:从上;
int val[1009][1009];
inline long long ut_max(long long a,long long b){
	return a>b?a:b;
}
inline long long ut_max(long long a,long long b,long long c){
	return ut_max(a,ut_max(b,c));
}
int main(){
	freopen("number.in","r",stdin);
	freopen("number.out","w",stdout);
	register int n=read(),m=read();
	for(register int i=1;i<=n;++i)
		for(register int j=1;j<=m;++j)
			val[i][j]=read();
	dp[0][1][1]=val[1][1];
	for(int i=2;i<=n;++i)dp[0][1][i]=-1e12;
	for(register int j=1;j<=m;++j){
		dp[1][j][n]=dp[2][j][1]=-1e12;
		if(j>1)for(register int i=1;i<=n;++i)
		dp[0][j][i]=ut_max(dp[0][j-1][i],dp[1][j-1][i],dp[2][j-1][i])+val[i][j];
		for(register int i=n-1;i;--i)
		dp[1][j][i]=ut_max(dp[1][j][i+1],dp[0][j][i+1])+val[i][j];
		for(register int i=2;i<=n;++i)
		dp[2][j][i]=ut_max(dp[2][j][i-1],dp[0][j][i-1])+val[i][j];
	}
	printf("%lld\n",ut_max(dp[0][m][n],dp[2][m][n]));
	fflush(stdout);
	return 0;
}

Over.

posted @ 2020-11-16 22:35  UnyieldingTrilobite  阅读(198)  评论(0编辑  收藏  举报