暑假模拟15

暑假模拟15

\(T_A\) 串串

简单字符串题,考虑枚举回文中心,哈希维护,没什么思维量,但是不好调。

wang54321 有高级 manacher 做法,大家快去膜拜她。

CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+100;
const ll mod=1000001011;
const ll base=2333;
char s[N];
int n,m;
bool b[N];
ll x,y,ny,p[N];
ll qpow(ll res,ll t){
	ll ans=1;
	while(t){
		if(t&1)ans=ans*res%mod;
		res=res*res%mod;
		t>>=1;
	}
	return ans;
}
int main()
{
	scanf("%d",&n);
	ny=qpow(base,mod-2);
	p[0]=1;
	for(int i=1;i<=1000000;i++){
		p[i]=p[i-1]*base%mod;
	}
	while(n--){
		scanf("%s",s+1);
		m=strlen(s+1);
		if(m==1){
			puts("1");
			continue;
		}
		for(int i=1;i<=m;i++){
			b[i]=0;
		}
		x=y=0;
		for(int i=m,len=0;i>=2;i--){
			if(x==y){
				if(i>m/2)b[i]=1;
				else b[i]=b[i+len];
			}
			if(i-1>m/2){
				y=(y+(s[i]-'a')*p[len])%mod;
				if(i!=m){
					x=((x-(s[i-1]-'a')*p[len-1])%mod+mod)%mod;
					x=x*p[2]%mod;
					x=(x+(s[i-len-1]-'a')*p[1])%mod;
				}
				x=(x+(s[i-len-2]-'a'))%mod;
				len++;
			}
			else if(i-1==m/2){
				x=0;
				for(int j=i-2;j>=1;j--){
					x=(x*base+s[j]-'a')%mod;
				}
				y=0;
				for(int j=i;j<2*i-2;j++){
					y=(y*base+s[j]-'a')%mod;
				}
				len=i-2;
			}
			else{
				x=((x-(s[i-1]-'a')*p[len-1])%mod+mod)%mod;
				if(i!=2){
					y=((y-(s[i+len]-'a')-(s[i+len-1]-'a')*base)%mod+mod)%mod;
					y=y*ny%mod*ny%mod;
					y=(y+(s[i]-'a')*p[len-2])%mod;
				}
				len--;
			}
		}
		for(int i=1;i<=m;i++){
			if(b[i])printf("%d ",i);
		}
		puts("");
	}
}

\(T_B\)排排

更简单的结论题,容易发现以下结论:

  1. 当且仅当 \(P\) 严格递增时,答案为 \(0\)

  2. 当且仅当存在一个 \(P_i=i\) 使得 \(P_1\dots P_i\) 是一个 \(1 \dots i\) 的排列,答案为 \(1\)

  3. 当且仅当 \(P_1=n,P_n=1\) ,答案为 \(3\)

  4. 其余情况答案均为 \(2\)

\(T_C\)序序

难题,不会

\(T_D\)桥桥

好题,虽然我没过,但我可以口胡。

首先将所有操作离线,分块,设块长为 \(T\)

对于每一块,按照边权降序排列 \(m\) 条边,并按如下方式排列块内操作:

修改按照出现顺序降序,查询按照重量降序排列,以后会有用。

对于每个查询,没有被修改的边权大于当前询问的边可能会有贡献,用并查集维护连通性。而被修改的边,如果对当前询问没有影响,回到上一种情况,如果有影响,则只考虑最后一次修改这条边的贡献。每次改变询问要求并查集可撤销(不要路径压缩)。由于每个块内操作并不多,暴力修改即可,保证复杂度正确,可能需要卡常。

还没过题,代码莫名原因 \(WA\) 了,先贴上。

Updata

对拍发现问题,代码中标注释的地方写错了,警示后人,清空 \(vis\) 数组一定要分清每条边排序前后的编号。

CODE
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
const int N=5e5+100;
int n,m,q,a,b,c,op,cnt,head[N];
int T,sum,lef[N],rig[N];
int f[N],siz[N],tot,p[N],ans[N];
bool vis[N],pd[N];
int dfn[N];
bool o[N];
struct query{
	int op,x,y,id;
}t[N];
struct Bridge{
	int from,to,wei,id;
}br[N];
bool cmp(query o,query p){
	if(o.op==p.op){
		if(o.op==2)return o.y>p.y;
		else return o.id>p.id;
	}
	else return o.op<p.op;
}
bool cmp1(Bridge o,Bridge p){
	return o.wei>p.wei;
}
int find(int x){
	if(x==f[x])return x;
	else return find(f[x]);
}
int sf[N],tf[N],top;
inline void merge(int u,int v,bool flag){
	int fx=find(u),fy=find(v);
	if(fx==fy)return ;
	if(siz[fx]>siz[fy]){
		if(flag){
			sf[++top]=fy;
			tf[top]=fx;
		}
		f[fy]=fx;
		siz[fx]+=siz[fy];
	}
	else{
		if(flag){
			sf[++top]=fx;
			tf[top]=fy;
		}
		f[fx]=fy;
		siz[fy]+=siz[fx];
	}
}
void solve(int l,int r,int x){
	sort(br+1,br+m+1,cmp1);
	for(int i=1;i<=m;i++){
		p[br[i].id]=i;
	}
	sort(t+l,t+r+1,cmp);
	for(int i=l;i<=r;i++){
		if(t[i].op==1)vis[t[i].x]=1;
	}
	for(int i=l,_=1;i<=r;i++){
		if(t[i].op==1)continue;
		while(_<=m){
			if(br[_].wei<t[i].y)break;
			if(!vis[br[_].id]){
				merge(br[_].from,br[_].to,0);
			}
			_++;
		}
		for(int j=l;j<=r;j++){
			if(t[j].op==2)continue;
			if(t[j].id>t[i].id)continue;
			if(pd[t[j].x])continue;
			pd[t[j].x]=1;
			if(t[j].y>=t[i].y){
				merge(br[p[t[j].x]].from,br[p[t[j].x]].to,1);
			}
		}
		for(int j=l;j<=r;j++){
			if(t[j].op==2)continue;
			if(pd[t[j].x])continue;
			if(br[p[t[j].x]].wei>=t[i].y){
				merge(br[p[t[j].x]].from,br[p[t[j].x]].to,1);
			}
			
		}
		ans[t[i].id]=siz[find(t[i].x)];
		while(top){
			siz[tf[top]]-=siz[sf[top]];
			f[sf[top]]=sf[top];
			top--;
		}
		for(int j=l;j<=r;j++){
			if(t[j].op==2)continue;
			pd[t[j].x]=0;
		}
	}
	for(int i=r;i>=l;i--){
		if(t[i].op==1){
			br[p[t[i].x]].wei=t[i].y;
			vis[t[i].x]=0;///
		}
	}
	for(int i=1;i<=n;i++){
		f[i]=i;
		siz[i]=1;
	}
}
int read(){
	int w=0;
	char cc=getchar();
	while(cc>'9'||cc<'0')cc=getchar();
	while(cc<='9'&&cc>='0'){
		w=w*10+cc-'0';
		cc=getchar();
	}
	return w;
}
int main()
{
	// freopen("q.in","r",stdin);
	// freopen("q.out","w",stdout);
	n=read();m=read();
	for(int i=1;i<=m;i++){
		br[i].from=read();
		br[i].to=read();
		br[i].wei=read();
		br[i].id=i;
	}
	for(int i=1;i<=n;i++){
		f[i]=i;
		dfn[i]=i;
		siz[i]=1;
	}
	q=read();
	T=750;
	for(int i=1;i<=q;i++){
		t[i].op=read();
		t[i].x=read();
		t[i].y=read();
		if(t[i].op==2){
			o[i]=1;
		}
		t[i].id=i;
	}
	sum=(q+T-1)/T;
	for(int i=1;i<=sum;i++){
		lef[i]=rig[i-1]+1;
		rig[i]=lef[i]+T-1;
	}
	rig[sum]=q;
	
	for(int i=1;i<=sum;i++){
		solve(lef[i],rig[i],i);
	}
	for(int i=1;i<=q;i++){
		if(o[i])printf("%d\n",ans[i]);
	}
}

闲话

感觉这次模拟赛后两题比较有难度,至少我不会,但赛时确实尽力在想了。前两题没挂分,其实这是比较基本的要求了,实际上大多数人,包括我,日常挂分都是很严重的。(反思一下自己)可能是因为想到做法就比较乐,容易犯一些意识不到的错误,即使大样例发现错误也会浪费时间。退一步说,不要过于相信大样例,虽说数据很大,但免不了存在偶然因素,对拍一下还是很必要的。(详见下次模拟赛,过了大样例还是狂挂不止)

一张红色的图

posted @ 2024-08-09 06:55  Abnormal123  阅读(8)  评论(0编辑  收藏  举报