200716-省选模拟1

200716-省选模拟1

T1

题目描述

题解

老套路了
维护左端nnn的个数L[i]L[i]L[i],右端iii的个数R[i]R[i]R[i]
ans=∑i=lr[s[i]==′o′](L[i]−L[l−1])(R[i]−R[r+1])ans=\sum_{i=l}^r[s[i]=='o'](L[i]-L[l-1])(R[i]-R[r+1])ans=i=lr[s[i]==o](L[i]L[l1])(R[i]R[r+1])
拆开维护四个前缀和即可

代码

#include<bits/stdc++.h>
#define M 2000009
#define ull unsigned long long
using namespace std;
int read(){
	int f=1,re=0;char ch;
	for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
	if(ch=='-'){f=-1,ch=getchar();}
	for(;isdigit(ch);ch=getchar()) re=(re<<1)+(re<<3)+ch-'0';
	return re*f;
}
int n,m,tot;
ull maxn,ans1[M],ans2[M],ans3[M],ans4[M],L[M],R[M];
char s[M];
inline void init(){
	int seed;
	scanf("%d",&seed);
	srand(seed);
}
inline void getQuery(int &l,int &r){
	l=(long long)rand()*rand()%n+1,r=(long long)rand()*rand()%n+1;
	if(l>r)std::swap(l,r); 
}
int main(){
	freopen("noi3.in","r",stdin);
	//freopen("noi.out","w",stdout);
	n=read(),m=read();
	scanf("%s",s+1);init();
	for(int i=1;i<=n;i++)
		L[i]=L[i-1]+(s[i]=='n');
	for(int i=n;i>=1;i--)
		R[i]=R[i+1]+(s[i]=='i');
	for(int i=1;i<=n;i++){
		ans1[i]=ans1[i-1];
		ans2[i]=ans2[i-1];
		ans3[i]=ans3[i-1];
		ans4[i]=ans4[i-1];
		if(s[i]=='o'){
			ans1[i]+=L[i];
			ans2[i]+=L[i]*R[i];
			ans3[i]++;
			ans4[i]+=R[i];
		}
	}
	for(int i=1;i<=m;i++){
		int l,r;ull ans=0;
		getQuery(l,r);
		ans=-(R[r+1]*(ans1[r]-ans1[l-1])-(ans2[r]-ans2[l-1])-R[r+1]*L[l-1]*(ans3[r]-ans3[l-1])+(ans4[r]-ans4[l-1])*L[l-1]);
		maxn=maxn^ans;
	}cout<<maxn<<endl;
	return 0;
}

T2

题目描述

题解

1,50分暴力:
我们发现两条路径显示是相反的,那么对n<=11n<=11n<=11的情况可以考虑从小到大枚举,拓扑判断即可
2,100分正解:
在这里插入图片描述

代码

#include<bits/stdc++.h>
#define M 200009
using namespace std;
int dfn[M],cnt,low[M],n,m,num,ans[M];
bool cut[M],vis[M],bj[M];
int nxt[M],to[M],first[M],tot;
int read(){
	int f=1,re=0;char ch;
	for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
	if(ch=='-'){f=-1,ch=getchar();}
	for(;isdigit(ch);ch=getchar()) re=(re<<1)+(re<<3)+ch-'0';
	return re*f;
}
void add(int x,int y){
	nxt[++tot]=first[x];
	first[x]=tot;
	to[tot]=y;
}
void tarjan(int u,int fa){
	cut[u]=0;
	dfn[u]=low[u]=++num;
	for(int i=first[u];i;i=nxt[i]){
		int v=to[i];
		if(v!=fa&&!bj[v]){
			if(!dfn[v]){
				tarjan(v,u);
				low[u]=min(low[u],low[v]);
				if(low[v]>=dfn[u]) cut[u]=1;
			}else low[u]=min(low[u],dfn[v]);
		}
	}
}
void addpoint(int u){
	bj[u]=1;
	for(int i=first[u];i;i=nxt[i]) vis[to[i]]=1;
}
int main(){
	freopen("messenger3.in","r",stdin);
	//freopen("messenger.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int x=read(),y=read();
		add(x,y),add(y,x);
	}tarjan(1,0);
	for(int i=2;i<=n;i++) if(cut[i]||!dfn[i]) puts("-1"),exit(0);
	addpoint(ans[1]=1),bj[1]=0;
	for(int i=2;i<=n;i++){
		memset(dfn,0,sizeof(dfn));
		num=0;tarjan(1,0);
		for(int j=2;j<=n;j++){
			if(!bj[j]&&vis[j]&&!cut[j]){
				addpoint(ans[i]=j);
				break;
			}
		}
	}for(int i=2;i<=n;i++)printf("%d ",ans[i]);
	printf("\n");
	for(int i=n;i>=2;i--)printf("%d ",ans[i]);
	return 0;
} 

T3

题目描述
咕咕咕~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值