1. 程式人生 > >Codechef:Sereja and Arcs(SEAARC)

Codechef:Sereja and Arcs(SEAARC)

傳送門

題解: 這種題顯然對出現次數分類討論一下。

出現少的O(S2)O(S^2)做,出現多的O(n)O(n)做,最後可以做到O(nnlogn)O(n \sqrt{n \log n})的複雜度。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) &&
(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ib==ob) ? -1 : *ib++; } inline int rd() { char ch=nc(); int i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();} return i*f; } const int N=1e5+50, L=1e5, mod=1e9+7, S=80, inv=(mod+
1)/2; inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);} inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);} inline int mul(int x,int y) {return (long long)x*y%mod;} inline void up(int &x,int y) {x=add(x,y);} inline void dn(int &x,int y) {x=dec(x,y);} int
n,a[N],l[N],r[N],c[N],last[N]; inline int calc_AABB() { static int cnt[N],s[N],s2[N],sum,ans; for(int i=1;i<=n;i++) { up(ans,s[a[i]]); up(s[a[i]],dec(sum,s2[a[i]])); up(sum,cnt[a[i]]); up(s2[a[i]],cnt[a[i]]); up(cnt[a[i]],1); } return ans; } inline int calc_ABBA(int x) { static int tot,suf[N],ans; tot=0,ans=0; static int cnt[N],s[N],s2[N]; for(int i=1;i<=n;i++) cnt[a[i]]=s[a[i]]=s2[a[i]]=0; for(int i=n;i>=1;i--) { suf[i]=add(suf[i+1],a[i]==x); tot+=(a[i]==x); } for(int i=1;i<=n;i++) { if(a[i]!=x) { up(ans,mul(cnt[a[i]],mul(suf[i],tot))); dn(ans,mul(s[a[i]],suf[i])); up(s[a[i]],suf[i]); up(cnt[a[i]],1); } } for(int i=1;i<=n;i++) cnt[a[i]]=s[a[i]]=0; for(int i=1;i<=n;i++) if(a[i]!=x && c[a[i]]<=S) { int res=0; up(res,s2[a[i]]); dn(res,mul(2,mul(suf[i],s[a[i]]))); dn(res,s[a[i]]); int aa=mul(suf[i],suf[i]); up(res,mul(cnt[a[i]],aa)); up(res,mul(cnt[a[i]],suf[i])); up(s2[a[i]],aa); up(cnt[a[i]],1); up(s[a[i]],suf[i]); up(ans,mul(res,inv)); } return ans; } int bit[N]; inline void inc(int i,int v) {for(;i;i-=i&(-i)) bit[i]+=v;} inline int ask(int i,int v=0) {for(;i<=n;i+=i&(-i)) v+=bit[i]; return v;} inline int solve() { int ans=0; for(int i=1;i<=n;i++) if(c[a[i]]<=S) { for(int j=r[i];j;j=r[j]) up(ans,ask(j+1)); for(int j=r[i];j;j=r[j]) inc(j,1); } memset(bit,0,sizeof(bit)); for(int i=1;i<=L;i++) if(c[i]<=S && last[i]) { vector <int> vec; for(int j=last[i];j;j=r[j]) vec.push_back(j); for(int j=0;j<vec.size();++j) { for(int k=j+1;k<vec.size();++k) dn(ans,ask(vec[k]+1)); for(int k=j+1;k<vec.size();++k) inc(vec[k],1); } for(int j=0;j<vec.size();++j) for(int k=j+1;k<vec.size();++k) inc(vec[k],-1); } return ans; } int main() { n=rd(); for(int i=1;i<=n;i++) ++c[a[i]=rd()]; for(int i=n;i;i--) { r[i]=last[a[i]]; last[a[i]]=i; } int ans=0, cnt=0; for(int i=1;i<=L;i++) if(c[i]) { int res=(long long)c[i]*(c[i]-1)/2%mod; up(ans,mul(cnt,res)); up(cnt,res); } dn(ans,calc_AABB()); for(int i=1;i<=L;i++) if(c[i]>S) dn(ans,calc_ABBA(i)); dn(ans,solve()); cout<<ans<<'\n'; }