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;
}