省选模拟18

不能说是挂分,只能说是菜,思考问题相当的不严谨!!

考试之前zxb告诉我,别人考过这个,全场只有一个人切掉了第一题

可能是受影响了吧,以后要避免

第一题,看了将近三个小时,于是只会暴力分

第二题,第一次看出来了绝顶聪明的人的策略,其实是题面给提示了

第三题,看了十分钟题面然后考试就结束了......

T1 货币

暴力就是尺取法......

考场上想到了启发式合并维护前趋,然而并不知道怎么用??!!

也想到了单调性,甚至想到了拆区间的次数有限!!!

然后就没了,发现用不上,原因是考场上拆区间的时候用的是枚举

合理利用线段树二分,哈哈哈,然后就能切掉了,注意写的时候小心点!!很麻烦

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
	int s=0,t=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*t;
}
const int N=1e5+5;
const int inf=0x3f3f3f3f;
struct D{
	int fa[N],siz[N];
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
}d;
int n,q,typ,ans,lans;
int pre[N],rig[N];
struct XDS{
	#define ls x<<1
	#define rs x<<1|1
	int mif[N*4],mnf[N*4],mxf[N*4],taf[N*4];//f
	int mip[N*4],mos[N*4];//pre
	int mnr[N*4];//question range
	void pushup(int x){
		mnr[x]=min(mnr[ls],mnr[rs]);
		mif[x]=min(mif[ls],mif[rs]);
		mxf[x]=max(mxf[ls],mxf[rs]);
		mnf[x]=min(mnf[ls],mnf[rs]);
		if(mip[ls]>mip[rs])mip[x]=mip[rs],mos[x]=mos[rs];
		else mip[x]=mip[ls],mos[x]=mos[ls];
	}
	void pushdown(int x,int l,int r){
		int mid=l+r>>1;
		taf[ls]=taf[x];mif[ls]=taf[x]-mid+1;
		mnf[ls]=mxf[ls]=taf[x];
		taf[rs]=taf[x];mif[rs]=taf[x]-r+1;
		mnf[rs]=mxf[rs]=taf[x];
		taf[x]=0;
	}
	void build(int x,int l,int r){
		if(l==r){
			mif[x]=n-l+1,mip[x]=0,mos[x]=l,mnr[x]=l;
			mnf[x]=mxf[x]=n;return ;
		}
		int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);pushup(x);
	}
	void insf(int x,int l,int r,int ql,int qr,int v){
		if(ql<=l&&r<=qr){taf[x]=v;mif[x]=v-r+1;mnf[x]=mxf[x]=v;return ;}
		int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
		if(ql<=mid)insf(ls,l,mid,ql,qr,v);
		if(qr>mid)insf(rs,mid+1,r,ql,qr,v);
		pushup(x);
	}
	int queryf(int x,int l,int r,int ql,int qr){
		//cerr<<x<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<mif[x]<<endl;
		if(ql<=l&&r<=qr)return mif[x];
		int mid=l+r>>1,ret=inf;if(taf[x])pushdown(x,l,r);
		if(ql<=mid)ret=min(ret,queryf(ls,l,mid,ql,qr));
		if(qr>mid)ret=min(ret,queryf(rs,mid+1,r,ql,qr));
		pushup(x);return ret;
	}
	void insp(int x,int l,int r,int pos,int v){
		if(l==r)return mip[x]=v,void();
		int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
		if(pos<=mid)insp(ls,l,mid,pos,v);
		else insp(rs,mid+1,r,pos,v);
		pushup(x);
	}
	int queryp(int x,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return mos[x];
		int mid=l+r>>1,ret=0;if(taf[x])pushdown(x,l,r);
		if(ql<=mid)ret=queryp(ls,l,mid,ql,qr);
		if(qr>mid){
			int tmp=queryp(rs,mid+1,r,ql,qr);
			if(!ret||pre[ret]>pre[tmp])ret=tmp;
		}pushup(x);return ret;
	}
	void insr(int x,int l,int r,int pos,int v){
		if(l==r)return mnr[x]=v,void();
		int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
		if(pos<=mid)insr(ls,l,mid,pos,v);
		else insr(rs,mid+1,r,pos,v);
		pushup(x);
	}
	int resl,resr;
	void init_res(){resl=n+1;resr=0;}
	void quf(int x,int l,int r,int v){
		if(mxf[x]<v||mnf[x]>v)return ;
		if(mnf[x]==v&&mxf[x]==v)return resl=min(resl,l),resr=max(resr,r),void();
		int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
		if(mxf[ls]>=v)quf(ls,l,mid,v);
		if(mnf[rs]<=v)quf(rs,mid+1,r,v);
		pushup(x);
	}
	int qul(int x,int l,int r,int qr,int v){//left qr && min>=v
		//cerr<<x<<" "<<l<<" "<<r<<" "<<qr<<" "<<v<<endl;
		if(r<=qr){
			if(mip[x]>=v)return l;
			if(l==r)return l+1;
			int mid=l+r>>1,ret;if(taf[x])pushdown(x,l,r);
			if(mip[rs]>=v)ret=qul(ls,l,mid,qr,v);
			else ret=qul(rs,mid+1,r,qr,v);
			pushup(x);return ret;
		}
		int mid=l+r>>1,ret=0;if(taf[x])pushdown(x,l,r);
		if(mid+1<=qr)ret=qul(rs,mid+1,r,qr,v);
		if(ret==mid+1||ret==0)ret=qul(ls,l,mid,qr,v);
		pushup(x);return ret;
	}
	#undef ls
	#undef rs
}xds;
set<int> st[N];
void change(int now){
	//cerr<<"now"<<" "<<now<<" "<<pre[now]<<endl;
	xds.insp(1,1,n,now,pre[now]);
	xds.init_res();xds.quf(1,1,n,now);
	int l=xds.resl,r=min(pre[now],xds.resr);
	//cerr<<"l"<<" "<<l<<" "<<r<<endl;
	while(l<=r){
		//cerr<<"S"<<l<<" "<<r<<" ";
		int pos=xds.qul(1,1,n,now,l);
		//cerr<<" "<<pos<<" ";
		int p=xds.queryp(1,1,n,pos,now);
		//cerr<<" "<<p<<" "<<pre[p]<<endl;
		xds.insf(1,1,n,l,min(r,pre[p]),pos-1);
		l=pre[p]+1;
	}
	//cerr<<"B"<<endl;
}
signed main(){
	freopen("currency.in","r",stdin);
	freopen("currency.out","w",stdout);
	n=read();q=read();typ=read();ans=n;
	fo(i,1,n){
		pre[i]=0;st[i].insert(i);rig[i]=i;
		d.fa[i]=i;d.siz[i]=1;
	}
	xds.build(1,1,n);
	while(q--){
		int x=(read()+typ*lans-1)%n+1,y=(read()+typ*lans-1)%n+1;
		int fx=d.find(x),fy=d.find(y);
		if(fx==fy){printf("%d\n",ans);continue;}
		if(d.siz[fy]>d.siz[fx])swap(fy,fx);
		d.fa[fy]=fx;d.siz[fx]+=d.siz[fy];
		rig[fx]=max(rig[fx],rig[fy]);
		xds.insr(1,1,n,fy,inf);xds.insr(1,1,n,fx,rig[fx]);
		for(int i:st[fy]){
			st[fx].insert(i);
			set<int>::iterator it=st[fx].find(i);
			if(it!=st[fx].begin()){
				pre[i]=*prev(it);change(i);
			}
			else pre[i]=0;
			if(next(it)!=st[fx].end()){
				int now=*next(it);pre[now]=i;
				change(now);
			}
		}st[fy].clear();
		printf("%d\n",lans=ans=xds.queryf(1,1,n,1,xds.mnr[1]));
	}
	return 0;
}

T2 比赛

发现隔一个能选一个,于是就每次暴力修改

然后数据比较水,链长是log就过了,后来被yspm用一条链卡掉了

于是摇摆兵仔细观察了数据,发现这是一条链,判走了......

这都不是重点,重点是他判完之后,没有自己A掉,然后跑到我这里来忽悠我......

暴力碾标算
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
	int s=0,t=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*t;
}
const int N=3e6+5;
int n,q,a[N],ans;
int buc[N],du[N],dep[N];
set<int> win[N];
void dfs2(int x,int v){
	if(!v)return ;dep[x]+=v;
	if(dep[x]==v)win[(x-a[x]+n)%n].erase(x);
	if(dep[x]==0)win[(x-a[x]+n)%n].insert(x);
	if(a[x]<=x&&a[x])dfs2(x-a[x],(!dep[x])?1:(dep[x]==v?-1:0));
}
signed main(){
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	n=read();q=read();
	fo(i,0,n-1)a[i]=read();
	fu(i,n-1,0)if((!dep[i])&&a[i]<=i&&a[i])dep[i-a[i]]++;
	fo(i,0,n-1)if(!dep[i])win[(i-a[i]+n)%n].insert(i);
	if(win[0].size())ans=*win[0].begin();
	else ans=0;
	printf("%d\n",ans);
	while(q--){
		int x=read(),y=read();
		if(a[x]<=x&&a[x]){
			dfs2(x-a[x],!dep[x]?-1:0);
			du[x-a[x]]--;
		}
		if(y<=x&&y){
			dfs2(x-y,(!dep[x])?1:0);
			du[x-y]++;
		}
		if(!dep[x])win[(x-a[x]+n)%n].erase(x),win[(x-y+n)%n].insert(x);
		a[x]=y;
		if(win[0].size())ans=*win[0].begin();
		else ans=0;
		printf("%d\n",ans);
	}
	return 0;
}

正解还没有打,是LCT

AC_code

T3 字符串

构造一个合法的AC自动机

如果有根了,那么我们需要判断这个根是否合法,可以将fail树上链接的两个点连向父亲的边用并查集缩起来!

然后直接构建自动机,这里构建方式就是爆跳fail,不然炸内存!!

剩下的就是观察性质了,。。。

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
	int s=0,t=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*t;
}
const int N=3e5+5;
int n,ans[N],can;
struct D{
	struct E{int to,nxt,id;}e[N*2];
	int head[N],rp,fe[N],dep[N],fa[N];
	void add_edg(int x,int y,int id){
		e[++rp].to=y;e[rp].nxt=head[x];
		e[rp].id=id;head[x]=rp;
	}
}d1,d2;
int fai[N];
int find(int x){return fai[x]==x?x:fai[x]=find(fai[x]);}
void dfs(int x,int f){
	d1.dep[x]=d1.dep[f]+1;d1.fa[x]=f;
	for(int i=d1.head[x];i;i=d1.e[i].nxt){
		int y=d1.e[i].to;
		if(y==f)continue;
		d1.fe[y]=d1.e[i].id;dfs(y,x);
	}
}
void dfss(int x,int f){
	d2.dep[x]=d2.dep[f]+1;d2.fa[x]=f;
	for(int i=d2.head[x];i;i=d2.e[i].nxt){
		int y=d2.e[i].to;
		if(y==f)continue;dfss(y,x);
	}
}
int buc[N],fail[N];
map<int,int> mp[N];
bool check(int rt){
	fo(i,1,n-1)fai[i]=i;
	dfs(rt,0);dfss(rt,0);can=0;
	fo(x,1,n){fail[x]=0;
		if(x==rt)continue;
		for(int i=d2.head[x];i;i=d2.e[i].nxt){
			int y=d2.e[i].to;
			if(d1.dep[y]<d1.dep[x]){fail[x]=y;continue;}
			int fx=find(d1.fe[x]),fy=find(d1.fe[y]);
			if(fx==fy)continue;fai[fx]=fy;
		}
		if(!fail[x])return false;
	}
	fo(i,1,n-1)if(find(i)==i)ans[i]=++can,buc[can]=0;
	queue<int> q;while(!q.empty())q.pop();
	mp[rt].clear();
	for(int i=d1.head[rt];i;i=d1.e[i].nxt){
		int y=d1.e[i].to;q.push(y);
		buc[ans[find(d1.e[i].id)]]++;
		mp[rt][ans[find(d1.e[i].id)]]=y;
		if(buc[ans[find(d1.e[i].id)]]>1)return false;
	}
	for(int i=d1.head[rt];i;i=d1.e[i].nxt)buc[ans[find(d1.e[i].id)]]--;
	while(!q.empty()){
		int x=q.front();q.pop();mp[x].clear();
		for(int i=d1.head[x];i;i=d1.e[i].nxt){
			int y=d1.e[i].to;
			if(d1.dep[y]<d1.dep[x])continue;
			if(d2.dep[x]<d2.dep[y]-1)return false;
			buc[ans[find(d1.e[i].id)]]++;
			mp[x][ans[find(d1.e[i].id)]]=y;
			if(buc[ans[find(d1.e[i].id)]]>1)return false;
			int now=x;q.push(y);
			while(now!=rt&&mp[fail[now]].find(ans[find(d1.e[i].id)])==mp[fail[now]].end())now=fail[now];
			if(now==rt&&fail[y]!=rt)return false;
			if(now!=rt&&fail[y]!=mp[fail[now]][ans[find(d1.e[i].id)]])return false;
		}
		for(int i=d1.head[x];i;i=d1.e[i].nxt){
			int y=d1.e[i].to;
			if(d1.dep[y]<d1.dep[x])continue;
			buc[ans[find(d1.e[i].id)]]--;
		}
	}
	return true;
}
map<pair<int,int>,int> ed;
int du[N];bool vs[N];int ps[N];
signed main(){
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	n=read();
	fo(i,1,n-1){
		int x=read(),y=read();
		d1.add_edg(x,y,i);d1.add_edg(y,x,i);
		ed.insert(make_pair(make_pair(min(x,y),max(x,y)),1));
	}
	fo(i,1,n-1){
		int x=read(),y=read();
		d2.add_edg(x,y,i);d2.add_edg(y,x,i);
		if(ed.find(make_pair(min(x,y),max(x,y)))!=ed.end()){
			du[x]++;du[y]++;vs[x]=vs[y]=true;
		}
	}
	fo(i,1,n)if(du[i]>=3){check(i);printf("%d\n",i);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
	fo(x,1,n)if(vs[x]){
		for(int i=d1.head[x];i;i=d1.e[i].nxt){
			int y=d1.e[i].to;
			if(!vs[y]&&!ps[y]){
				ps[y]=true;
				for(int j=d2.head[y];j;j=d2.e[j].nxt){
					int z=d2.e[j].to;
					if(vs[z])if(check(z)){printf("%d\n",z);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
					for(int k=d2.head[z];k;k=d2.e[k].nxt){
						int w=d2.e[k].to;
						if(vs[w])if(check(w)){printf("%d\n",w);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
					}
				}
			}
		}
	}
}
posted @ 2022-02-20 21:31  fengwu2005  阅读(55)  评论(0编辑  收藏  举报