6.11 考试修改+总结

Posted _Vertical

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.11 考试修改+总结相关的知识,希望对你有一定的参考价值。

第三题至今没敢写,感觉好恐怖QAQ

今天考得好糟糕

 

第一题只写了10分的暴力+(k=1)20分的网络流

后来题解告诉我k>1的时候可以分治到k=1,每层分治解决方法是同k=1的

考试的时候没有注意到2^k这个比较神奇的可以分治的性质

而且自己考场上丝薄了,没有发现因为是二分图可以直接跑欧拉回路的性质,而是裸套网络流模型

 

第二题其实已经接近想出了题解

自己考试的时候成功证明了暴力的复杂度是线性的

但是没有想到如何寻找0-1对,然后就只能暴力用Splay维护1所在的位置了

默默祈祷数据不要太卡我的做法,结果最后只比裸暴力分多10分,只是悲桑

考后跟zcg交流一下发现维护一下hash值之后每次二分就可以找到0-1对了(考场上在想什么系列

但是这样会T或者WA(因为貌似卡自然溢出?瞎改几个base就可以了

还有一种做法是在线段树上直接劈开区间,然后如果哈希值相等的区间就不递归,否则递归下去改

时间复杂度略微有些玄学,但是跑的比hash+二分快

自己写的貌似会T一个点,不过懒得玩常数优化了

 

第三题貌似是弱化版的火龙果

不过LCT要维护一些奇怪的东西,考试的时候没有想出来怎么维护

后来看题解发现维护的方法类似疯狂的重心,LCT维护子树和

每次暴力删最大边看看是否可以不丢失解

但是感觉要码这样一坨东西好鬼畜啊

被莫名卡了常数,丢了20分的暴力分QAQ

 

最后貌似交到OJ上rank2?

%%%zcg

 

第一题代码:

写欧拉回路的时候写的比较鬼畜,但也只能这样写来保证O(m)的性质了(YY了好久,感谢jkxing

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<set>
using namespace std;

const int maxn=400010;
int n,m,k,T;
int deg[maxn];
struct Edge{
	int u,v,id;
}c[maxn],Q1[maxn],Q2[maxn];
int Ans[maxn];
int h[maxn],cnt=0;
bool vis[maxn];
int check[maxn],tim;
int st[maxn],top=0;
struct edge{
	int to,next,w;
}G[maxn];

void add(int x,int y,int z=0){
	++cnt;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt;
	vis[cnt]=false;
}
void read(int &num){
	num=0;char ch=getchar();
	while(ch<‘!‘)ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar();
}
void Get_euler(int u,int f){
	check[u]=tim;
	for(int i=h[u];i;i=h[u]){
		if(vis[i]){h[u]=G[i].next;continue;}
		int v=G[i].to;
		vis[i]=vis[i^1]=true;
		G[i].w=G[i^1].w=f;
		h[u]=G[i].next;
		Get_euler(v,f^1);
	}return;
}
void Solve(int L,int R,int k){
	if(!k)return;
	cnt=1;tim++;top=0;
	for(int i=L;i<=R;++i){
		int u=c[i].u,v=c[i].v;
		add(u,v);add(v,u);
		if(check[u]!=tim)check[u]=tim,st[++top]=u;
		if(check[v]!=tim)check[v]=tim,st[++top]=v;
	}tim++;
	for(int i=1;i<=top;++i){
		if(check[st[i]]!=tim)Get_euler(st[i],0);
	}
	int l1=0,l2=0;
	for(int i=L;i<=R;++i){
		int now=(i-L+1)<<1;
		int u=c[i].id;
		h[c[i].u]=h[c[i].v]=0;
		Ans[u]=(Ans[u]<<1)|G[now].w;
		if(G[now].w)Q2[++l2]=c[i];
		else Q1[++l1]=c[i];
	}
	for(int i=1;i<=l1;++i)c[L+i-1]=Q1[i];
	for(int i=1;i<=l2;++i)c[L+l1+i-1]=Q2[i];
	Solve(L,L+l1-1,k-1);Solve(L+l1,R,k-1);
}

int main(){
	int __size__=128<<20;
	char *__p__=(char*)malloc(__size__)+__size__;
	__asm__("movl %0, %%esp\n"::"r"(__p__));
	while(scanf("%d%d",&n,&m)==2){
		memset(deg,0,sizeof(deg));
		for(int i=1;i<=m;++i){
			read(c[i].u);read(c[i].v);
			c[i].id=i;
			deg[c[i].u]++;deg[c[i].v]++;
		}
		for(k=1;k;++k){
			int mk=(1<<k);
			bool flag=false;
			for(int i=1;i<=n;++i)if(deg[i]%mk!=0||!deg[i]){flag=true;break;}
			if(flag)break;
		}k--;
		if(!k)printf("-1\n");
		else{
			memset(Ans,0,sizeof(Ans));
			Solve(1,m,k);
			printf("%d\n",k);
			for(int i=1;i<=m;++i)printf("%d ",Ans[i]+1);
			printf("\n");
		}	
	}return 0;
}

第二题代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int maxn=1000010;
const int base=13331;
int n,m,type,L,R,len,p,x,y;
char s[maxn];
int sum[maxn<<2];
LL xp[maxn];
LL h[maxn<<2];

void read(int &num){
	num=0;char ch=getchar();
	while(ch<‘!‘)ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar();
}
void build(int o,int L,int R){
	if(L==R){
		h[o]=s[L];
		sum[o]=h[o]-‘0‘;
		return;
	}
	int mid=(L+R)>>1;
	int l=(o<<1),r=(l|1);
	build(l,L,mid);build(r,mid+1,R);
	h[o]=h[l]*xp[R-mid]+h[r];
	sum[o]=sum[l]+sum[r];
}
void UPD(int o,int L,int R){
	if(L==R){
		h[o]^=1;
		sum[o]^=1;
		return;
	}
	int mid=(L+R)>>1;
	int l=(o<<1),r=(l|1);
	if(p<=mid)UPD(l,L,mid);
	else UPD(r,mid+1,R);
	h[o]=h[l]*xp[R-mid]+h[r];
	sum[o]=sum[l]+sum[r];
}
LL ask(int o,int L,int R){
	if(L>=x&&R<=y)return h[o];
	int mid=(L+R)>>1;
	if(y<=mid)return ask(o<<1,L,mid);
	else if(x>mid)return ask(o<<1|1,mid+1,R);
	else{
		LL A=ask(o<<1,L,mid);
		LL B=ask(o<<1|1,mid+1,R);
		return A*xp[min(y,R)-mid]+B;
	}
}
int ask_S(int o,int L,int R){
	if(L>=x&&R<=y)return sum[o];
	int mid=(L+R)>>1;
	if(y<=mid)return ask_S(o<<1,L,mid);
	else if(x>mid)return ask_S(o<<1|1,mid+1,R);
	else return ask_S(o<<1,L,mid)+ask_S(o<<1|1,mid+1,R);
}

int main(){
	freopen("and.in","r",stdin);
	freopen("and.out","w",stdout);
	read(n);read(m);
	scanf("%s",s+1);
	xp[0]=1;
	for(int i=1;i<=n;++i)xp[i]=xp[i-1]*base;
	build(1,1,n);
	while(m--){
		read(type);
		if(type==1){
			read(L);read(R);read(len);
			int l=1,r=len;
			while(true){
				while(l<r){
					int mid=(l+r)>>1;
					x=L;y=L+mid-1;
					LL A=ask(1,1,n);
					x=R;y=R+mid-1;
					LL B=ask(1,1,n);
					if(A==B)l=mid+1;
					else r=mid;
				}
				x=L+r-1;y=R+r-1;
				int A=s[x]-‘0‘,B=s[y]-‘0‘;
				if(A==B)break;
				if(A==1)s[x]=‘0‘,p=x,UPD(1,1,n);
				else s[y]=‘0‘,p=y,UPD(1,1,n);
				l=r;r=len;
			}
		}else if(type==2){
			read(L);p=L;
			if(s[L]==‘1‘)s[L]=‘0‘;
			else s[L]=‘1‘;
			UPD(1,1,n);
		}else{
			read(L);read(R);read(len);
			x=L;y=R;
			int now=ask_S(1,1,n);
			if(len==1)printf("%d\n",now);
			else printf("%d\n",R-L+1-now);
		}
	}return 0;
}

第三题看看zcg他们能不能搞出来吧

感觉自己要写的话一个晚上药丸啊

以上是关于6.11 考试修改+总结的主要内容,如果未能解决你的问题,请参考以下文章

5.26 考试修改+总结

6.11模拟赛总结

6.3 考试修改+总结

5.27 考试修改+总结

5.28 考试修改+总结

6.1 考试修改+总结