牛客周赛 round 82 A--F

A.夹心饼干
一个string
#include<bits/stdc++.h>
using namespace std;
int main(){
	string s;
	cin>>s;
	if(s[0]==s[2]) cout<<"YES";
	else cout<<"NO";
	return 0;
}
B.食堂大作战1.0
一个set求size()
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+200;
int a[N];
set<int>st;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		st.insert(a[i]);
	}
	if(st.size()==n) cout<<"YES";
	else cout<<"NO";
	return 0;
}
C.食堂大作战2.0
一个set求size()+sort()排序即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+200;
struct node{
	int num,pos;
}d[N];
set<int>st;
int cmp(struct node a,struct node b){
	return a.num<b.num;
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>d[i].num;
		d[i].pos=i;
		st.insert(d[i].num);
	}
	if(st.size()!=n) cout<<"NO";
	else{
		cout<<"YES"<<endl;
		sort(d+1,d+1+n,cmp);
		for(int i=1;i<=n;i++){
			cout<<d[i].pos<<" ";
		}
	}
	return 0;
}
D.小苯的排列计数
一个不合法的序列具有以下三种中至少一种的情况
1.序列的最后一位不为1
2.序列的某一位比上一位大(除了第一位)
3.序列中出现可选的数字个数<需要选的数字个数的情况(如:4 3 3 1,明显第三位数字选不了
剩下的都是合法序列
对于合法序列求总方案数,其中一种方法是:每一个不确定的数的位置上,可以填的数字个数的总和相乘
求当前位置的不确定的数(计算当前位置可选的数的数量):即为:总的区间大小-已经确定的数个数-不确定的数中已经被选过的数个数
总的区间:设当前位置为x,那么其可以选的数的下界为p[x],上界为n,这其中包含(n-p[x]+1)个数
已经确定的数:用vector<int>a存储确定的数,易得,若序列的某一位比上一位小,那么这一位数字唯一确定
不确定的数中已经被选过的数:设一个变量presum,每一次将用过的数的个数加入presum里即可(此处也可以预处理,用vector<int>tmp存储某一段区间内需要的数个数,与a同步记录)

具体实现可以看下面代码,基本的关键语句都有注释
(注意取模!)
#include<bits/stdc++.h>
#define int long long int
using namespace std;
const int N=1e6+200;
int MOD=998244353;
int p[N];
void solve() {
	int n,ans=1;
	cin>>n;
	for(int i=1; i<=n; i++) {
		cin>>p[i];
	}
	if(p[n]!=1) { //如果p数组的最后一个值不是1,那一定不合法
		cout<<"0"<<endl;
		return ;
	}
	for(int i=2; i<=n; i++) { //如果p数组存在后面的数字大于前面的数字的情况,也不合法
		if(p[i]>p[i-1]) {
			cout<<"0"<<endl;
			return ;
		}
	}
	vector<int>a,tmp;
	int pos=1;
	while(pos<=n) { //往a数组里面存入已经确定的数字 
		a.push_back(p[pos]); //第一个数字一定确定,存入a 
		int cnt=0,nxt=pos+1;
		while (nxt<=n && p[nxt] == a.back()) { //如果a数组中的最后一个数仍然是目前的最小值 
			cnt++; //需要选的数字个数+1 
			nxt++; //目前位置+1 
		}
		tmp.push_back(cnt); //tmp数组存储对应需要选的数字个数 
		pos=nxt;
	}
	int prenum=0; //persum:前面选过的数字总个数
	int si=a.size();
	for(int i=0; i<si; i++) { //注意此处遍历的是a
		int tmpnum=(n-a[i]+1)-(i+1)-prenum; //计算可选的数字个数
		if (tmpnum<tmp[i]) { //可选的数字个数<需要选的数字个数
			ans=0;
			break;
		}
		for (int j=0; j<tmp[i]; j++) { //计算目前这一段数字对于ans的贡献
			ans=ans*(tmpnum-j)%MOD;
		}
		prenum+=tmp[i]; //更新前面选过的数字总个数
	}
	cout<<ans%MOD<<endl;
	return ;
}

signed main() {
	int T;
	cin>>T;
	while(T--) {
		solve();
	}
	return 0;
}

E.和+和
(下面的分析默认数组内第一个元素存放的下标为1
对于a数组,新开一个minsuma数组,其中minsuma[x]表示a数组在[1,x]内取m个数的最小值
对于b数组,新开一个minsumb数组,其中minsumb[x]表示b数组在[x,n]内取m个数的最小值
对于求minsuma[x]与minsumb[x],一种比较简单的方法是:开两个优先队列quea,queb,分别用于存储目前a数组与b数组的m个最小值
对于a,当遇到下一个元素时,如果这一个元素小于quea.top(),那么将这一个元素存入队列,否则不存,对于b同理
最后的答案就是ans=min(ans,minsuma[i]+minsumb[i+1]); (i的范围为[m,n-m]),相当于求前i个数内取a的m个数,第(i+1)个数到第n个数内取b的m个数
具体实现可以看下面代码
(P.S.:请仔细分析下标的范围,不要大了或小了
#include<bits/stdc++.h>
#define int long long int
using namespace std;
const int N=2e5+200;
int a[N],b[N],minsuma[N],minsumb[N];
priority_queue<int>quea;
priority_queue<int>queb;
signed main() {
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
	}
	for(int i=1; i<=n; i++) {
		cin>>b[i];
	}
	for(int i=1; i<=m; i++) {
		minsuma[m]+=a[i];
		quea.push(a[i]);
	}
	for(int i=m+1; i<=n-m; i++) {
		int tmp=quea.top();
		if(a[i]<tmp) {
			quea.pop();
			quea.push(a[i]);
			minsuma[i]=minsuma[i-1]-tmp+a[i];
		}else{
			minsuma[i]=minsuma[i-1];
		}
	}
	for(int i=n; i>=n-m+1; i--) {
		minsumb[n-m+1]+=b[i];
		queb.push(b[i]);
	}
	for(int i=n-m; i>=m+1; i--) {
		int tmp=queb.top();
		if(b[i]<tmp) {
			queb.pop();
			queb.push(b[i]);
			minsumb[i]=minsumb[i+1]-tmp+b[i];
		}else{
			minsumb[i]=minsumb[i+1];
		}
	}
	int minn=1e18;
	for(int i=m;i<=n-m;i++){
		minn=min(minn,minsuma[i]+minsumb[i+1]);
	}
	cout<<minn<<endl;
	return 0;
}

F.怎么写线性SPJ
画出来之后发现这个数字的排序像是一棵树,n取几就从左往右取几个数输出,所以可以用lowbit(x),即x&(-x)实现
下面代码中的__lg(x)函数能够实现对于log2(x)的向下取整功能;
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	cout<<__lg(n)+1<<endl;
	for(int i=1;i<=n;i++){
		cout<<__lg(i&(-i))+1<<" ";
	}
	return 0;
}
(P.S.:最后一题看了半小时没看出来的我真的很小丑)