3.21省选模拟测试

3.21省选模拟测试

心得

T1 P6008

题目大意

题目描述

题解

并查集

代码

#include<bits/stdc++.h>
#define M 1000009
#define int 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<<3)+(re<<1)+ch-'0';
	return re*f;
}
int fx[3]={1,0,0};
int fy[3]={0,1,-1};
const int mod=1e9+7;
int f[M],dp[M],mp[1009][1009],n,m,ans=1,vis[M];
char s[1009];
int id(int x,int y){return (x-1)*m+y;}
int find(int x){
	if(f[x]==x) return x;
	return f[x]=find(f[x]);
}
void unionx(int x,int y){
	int lx=find(x),ly=find(y);
	if(lx==ly) return;
	f[lx]=ly,dp[ly]=(dp[lx]*dp[ly])%mod;
}
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n*m;i++) f[i]=i,dp[i]=1;
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
			if(s[j]=='#') mp[i][j]=1;
			else mp[i][j]=0;
	}
	for(int i=n-1;i>=2;i--){
		for(int j=2;j<m;j++){
			if(mp[i][j]) continue;
			for(int k=0;k<3;k++){
				int tx=i+fx[k],ty=j+fy[k];
				if(!mp[tx][ty]) unionx(id(i,j),id(tx,ty));
			}
		}
		for(int j=2;j<m;j++){
			if(mp[i][j]) continue;
			int fa=find(id(i,j));
			if(!vis[fa]) dp[fa]=(dp[fa]+1)%mod,vis[fa]=1; 
		}
		for(int j=2;j<m;j++){
			if(mp[i][j]) continue;
			int fa=find(id(i,j));
			vis[fa]=0;
		}
	}
	for(int i=n-1;i>=2;i--){
		for(int j=2;j<m;j++){
			if(mp[i][j]) continue;
			if(f[id(i,j)]==id(i,j)) ans=(ans*dp[f[id(i,j)]])%mod;
		}
	}printf("%lld\n",ans);
	return 0;
} 

T2 P6009

题目大意

题目描述

题解

CDQ分治/矩阵快速幂(只会CDQ分治 qwq)

代码

#include<bits/stdc++.h>
#define M 200009
#define int 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<<3)+(re<<1)+ch-'0';
	return re*f;
}
const int mod=1e9+7;
queue<int>q1;
struct data{int x,y;}q[M];
int n,tr[25],ans[M],sum[M],f[25][M],m,k,a[M];
int lowbit(int i){return i&(-i);}
void update(int x,int y){while(x<=k) tr[x]=(tr[x]+y)%mod,x+=lowbit(x);}
int query(int x){
	int g=0;
	while(x>0) g=(tr[x]+g)%mod,x-=lowbit(x);
	return g;
}
void cdq(int l,int r){
	if(!q1.size()) return;
	if(l==r){
		while(q1.size()) ans[q1.front()]=2,q1.pop(); 
		return;
	}int mid=(l+r)>>1;
	for(int i=1;i<=k;i++){
		memset(tr,0,sizeof(tr));
		for(int j=mid;j>=l;j--){
			f[i][j]=(query(k-a[j]+1)+(a[j]==i))%mod;
			update(k-a[j]+1,f[i][j]);
		}for(int j=mid-1;j>=l;j--) f[i][j]=(f[i][j+1]+f[i][j])%mod;
	}for(int i=l;i<=mid;i++) f[1][i]=(f[1][i]+1)%mod; 
	for(int i=1;i<=k;i++){
		memset(tr,0,sizeof(tr));
		for(int j=mid+1;j<=r;j++){
			f[i][j]=(query(a[j])+(a[j]==i))%mod;
			update(a[j],f[i][j]);
		}for(int j=mid+2;j<=r;j++) f[i][j]=(f[i][j-1]+f[i][j])%mod;
	}for(int i=mid+1;i<=r;i++) f[k][i]=(f[k][i]+1)%mod; 
	queue<int>q2,q3;
	while(!q1.empty()){
		int id=q1.front();q1.pop();
		if(q[id].y<=mid) q2.push(id);
		else if(q[id].x>mid) q3.push(id);
		else{
			for(int i=k;i>=1;i--) sum[i]=(sum[i+1]+f[i][q[id].y])%mod;
			for(int i=1;i<=k;i++) ans[id]=(ans[id]+sum[i]*f[i][q[id].x]%mod)%mod;
		}
	}while(q2.size()) q1.push(q2.front()),q2.pop();
	cdq(l,mid);while(q1.size()) q1.pop();
	while(q3.size()) q1.push(q3.front()),q3.pop();
	cdq(mid+1,r);while(q1.size()) q1.pop();
}
signed main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++) a[i]=read();
	m=read();
	for(int i=1;i<=m;i++) q[i].x=read(),q[i].y=read(),q1.push(i);
	cdq(1,n);
	for(int i=1;i<=m;i++) printf("%lld\n",ans[i]%mod);
	return 0;
}

T3 P6010

题目大意

题目描述

题解

代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值