2019/10/05 校内模拟

T1

原题:[Codeforces 19E]Fairy

先不写题解了,可以参考这里

主要就是图是二分图的充要条件是没有基环,然后判断几种情况即可。

#include<bits/stdc++.h>
#define N 5000005
using namespace std;
int n,m,t=1;
int dep[N],vis[N],odd[N],even[N],ans[N];
int first[N],v[N<<1],nxt[N<<1];
struct edge{int u,v,odd,even,flag;}e[N];
int in(){
	int x=0;char c=getchar();
	while(!isdigit(c))  c=getchar();
	while(isdigit(c))  x=((x+(x<<2))<<1)+(c^'0'),c=getchar();
	return x;
}
void out(int x){
	if(x>9)  out(x/10);
	putchar(x%10+'0');
}
void add(int x,int y){
	nxt[++t]=first[x],first[x]=t,v[t]=y;
}
void dfs1(int x){
	vis[x]=1;
	for(int i=first[x];i;i=nxt[i]){
		int to=v[i];
		if(vis[to])  continue;
		dep[to]=dep[x]+1,e[i/2].flag=1,dfs1(to);
	}
}
void dfs2(int x){
	vis[x]=1;
	for(int i=first[x];i;i=nxt[i]){
		int to=v[i];
		if(vis[to])  continue;
		dfs2(to),even[x]+=even[to],odd[x]+=odd[to];
		e[i/2].even=even[to],e[i/2].odd=odd[to];
	}
}
int main(){
	n=in(),m=in();
	for(int i=1;i<=m;++i){
		e[i].u=in(),e[i].v=in();
		add(e[i].u,e[i].v),add(e[i].v,e[i].u);
	}
	for(int i=1;i<=n;++i)
		if(!vis[i])  dfs1(i);
	int cnt=0;
	for(int i=1;i<=m;++i){
		if(e[i].flag)  continue;
		int u=e[i].u,v=e[i].v;
		if(dep[u]>dep[v])  swap(u,v);
		if((dep[v]-dep[u])&1)  even[v]++,even[u]--;
		else  odd[v]++,odd[u]--,cnt++,e[i].odd++;
	}
	if(!cnt){
		out(m),putchar('\n');
		for(int i=1;i<=m;++i)  out(i),putchar(' ');
		return 0;
	}
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;++i)
		if(!vis[i])  dfs2(i);
	int tot=0;
	for(int i=1;i<=m;++i){
		if(e[i].flag){
			if(e[i].odd==cnt&&!e[i].even)  ans[++tot]=i;
		}
		else  if(e[i].odd&&cnt==1)  ans[++tot]=i;
	}
	out(tot),putchar('\n');
	for(int i=1;i<=tot;++i)  out(ans[i]),putchar(' ');
	return 0;
}

T2

原题:[BZOJ 3682]Phorni

1 1 1

我们可以直接用线段树维护大小关系,在合并区间的时候二分 + + + 哈希判断大小关系即可。

时间复杂度 O ( n log ⁡ 2 n ) O(n\log^2n) O(nlog2n),考试数据比较强只有 10 10 10 分。

2 2 2

这是后缀平衡树的模板题。

相当于是建一颗平衡树,每个节点代表一个后缀,相当于是在平衡树上维护后缀的偏序关系。

有关后缀平衡树我就不都说了,能够 O ( 1 ) O(1) O(1) 比较的标号法挺强大的。可以看看这篇博客

代码实现就用的替罪羊 + + + 线段树

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=9e5+5;
char S[M],op[5];
int n,m,len,P[N];
namespace Scapegoat{
	double L[M],R[M],alpha=0.75;
	int root,tot,*bad,lc[M],rc[M],Size[M],order[M];
	double val(int x)  {return (!x)?-1e18:L[x]+R[x];}
	bool comp(int x,int y)  {return (S[x]<S[y])||(S[x]==S[y]&&val(x-1)<val(y-1));}
	void ins(int &u,int x,double l,double r){
		if(!u)  {u=x,L[u]=l,R[u]=r,Size[u]=1;return;}
		double mid=(l+r)/2;++Size[u];
		if(comp(u,x)){
			ins(rc[u],x,mid,r);
			if(Size[rc[u]]>alpha*Size[u])  bad=&u;
		}
		else{
			ins(lc[u],x,l,mid);
			if(Size[lc[u]]>alpha*Size[u])  bad=&u;
		}
	}
	void inorder(int x){
		if(lc[x])  inorder(lc[x]);
		order[++tot]=x;
		if(rc[x])  inorder(rc[x]);
	}
	int build(int l,int r,double vl,double vr){
		if(l>r)  return 0;
		int mid=(l+r)>>1;double Mid=(vl+vr)/2;
		int u=order[mid];L[u]=vl,R[u]=vr,Size[u]=r-l+1;
		lc[u]=build(l,mid-1,vl,Mid);
		rc[u]=build(mid+1,r,Mid,vr);
		return u;
	}
	void rebuild(int &k){
		tot=0,inorder(k);
		k=build(1,tot,L[k],R[k]);
	}
	void Insert(int i){
		bad=NULL,ins(root,i,-1e9,1e9);
		if(bad!=NULL)  rebuild(*bad);
	}
}
using namespace Scapegoat;
namespace Segment{
	int mn[N<<2];
	int Min(int x,int y)  {return (P[x]!=P[y]?val(P[x])<val(P[y]):x<y)?x:y;}
	#define mid ((l+r)>>1)
	void build(int root,int l,int r){
		if(l==r)  {mn[root]=l;return;}
		build(root<<1,l,mid),build(root<<1|1,mid+1,r);
		mn[root]=Min(mn[root<<1],mn[root<<1|1]);
	}
	void Modify(int root,int l,int r,int x){
		if(l==r)  {mn[root]=x;return;}
		if(x<=mid)  Modify(root<<1,l,mid,x);
		else  Modify(root<<1|1,mid+1,r,x);
		mn[root]=Min(mn[root<<1],mn[root<<1|1]);
	}
	int Query(int root,int l,int r,int x,int y){
		if(l>=x&&r<=y)  return mn[root];
		if(y<=mid)  return Query(root<<1,l,mid,x,y);
		if(x> mid)  return Query(root<<1|1,mid+1,r,x,y);
		return Min(Query(root<<1,l,mid,x,y),Query(root<<1|1,mid+1,r,x,y));
	}
	#undef mid
}
using namespace Segment;
int main(){
	scanf("%d%d%d%s",&n,&m,&len,S+1);
	reverse(S+1,S+len+1);
	for(int i=1;i<=len;++i)  Insert(i);
	for(int i=1;i<=n;++i)  scanf("%d",&P[i]);
	build(1,1,n);
	int x,pos,l,r,last=0;
	while(m--){
		scanf("%s",op);
		if(op[0]=='I')  scanf("%d",&x),x^=last,S[++len]=x+'a',Insert(len);
		else  if(op[0]=='C')  scanf("%d%d",&x,&pos),P[x]=pos,Modify(1,1,n,x);
		else  scanf("%d%d",&l,&r),printf("%d\n",last=Query(1,1,n,l,r));
	}
	return 0;
}

T3

原题:[Codeforces 768G]The Winds of Winter

还没写。

大佬博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值