题目大意:给出一个区间,并给定应两两相等的数位的数对,求满足的数的个数。
范围:1e5
做法:
先用并查集,将互相相等的树连成一块,统计块的个数,从高位到低位扫描,然后容斥即可
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<queue> #include<ctime> #define MAXN 200005 #define ll long long #define maxn 15 #define maxs 1000005 #define inf 1e9 #define eps 1e-9 using namespace std; inline char gc() { static char now[1<<16],*S,*T; if (T==S) { T=(S=now)+fread(now,1,1<<16,stdin); if (T==S) return EOF; } return *S++; } inline ll readlong() { ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x*=10; x+=ch-'0'; ch=getchar(); } return x*f; } inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x*=10; x+=ch-'0'; ch=getchar(); } return x*f; } void putint(long long t) { int ans[40]= {0}; for(; t; t/=10)ans[++ans[0]]=t%10; for(; ans[0]; ans[0]--)putchar('0'+ans[ans[0]]); putchar('\n'); } const int mod=19260817; const int N=100005; int n,q; int L[N],R[N]; int fa[N]; int getf(int x){ if(fa[x]==x){ return x; } return fa[x]=getf(fa[x]); } int ksm(int x,int k){ int ret=1; int ans=x%mod; while(k){ if(k&1){ ret=1ll*ret*ans%mod; } ans=1ll*ans*ans%mod; k>>=1; } return ret; } int dfs(int a[]){//实则是求从0算至a[]这一区间的个数 int tot=0; for(int i=1;i<=n;i++){ if(fa[i]==i){ tot++; } } // cout<<"tot="<<tot<<endl; int ans=0; for(int i=n;i>0;i--){ if(fa[i]==i){ tot--; ans=(ans+a[i]*ksm(10,tot))%mod; } if(a[getf(i)]<a[i]){ ans=(ans+ksm(10,tot))%mod; } if(a[getf(i)]!=a[i]){ break; } } return ans; } int main(){ n=read(); for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=n;i++){ L[i]=read(); } for(int i=1;i<=n;i++){ R[i]=read(); } q=read(); while(q--){ int x=read(); int y=read(); x=getf(x); y=getf(y); fa[min(x,y)]=max(x,y); // cout<<"fa["<<min(x,y)<<"]"<<"= "<<max(x,y); } // cout<<dfs(R)<<" "<<dfs(L)<<endl; cout<<(dfs(R)+mod-dfs(L))%mod; return 0; }