1. 程式人生 > >bzoj 5110 Yazid的新生舞會

bzoj 5110 Yazid的新生舞會

題目大意:

一個數列,求有多少個區間$[l,r]$滿足該區間的眾數出現次數大於$\lceil \frac{r-l}{2} \rceil$

思路:

對於一個區間滿足條件的眾數明顯是唯一的 所以設該數的字首和陣列為$S$

則一個區間$(l,r]$滿足條件滿足$2 \times (S_r-S_l)>(r-l)$ 移項後得到$2 \times S_r-r>2 \times S_l-l$

則對於$2 \times S_i-i$建立函式發現該函式由斜率為$\pm 1$組成

所有函式的關鍵點總數為$n$ 對於$y$軸建立權值線段樹 發現中間連續的一段的貢獻為一次函式

寫一波一次函式即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #include<set>
11 #define rep(i,s,t) for(register int i=(s),i__end=(t);i<=i__end;++i)
12
#define dwn(i,s,t) for(register int i=(s),i__end=(t);i>=i__end;++i) 13 #define ren(x) for(register int i=fst[x];i;i=nxt[i]) 14 #define pb(a,x) vec[a].push_back(x); 15 #define ll long long 16 #define inf 2139062143 17 #define MAXN 1001000 18 using namespace std; 19 inline int read() 20 { 21 int x=0,f=1
;char ch=getchar(); 22 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 23 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 int n,N,tp,g[MAXN],hsh[MAXN],m,tagk[MAXN<<2],tagb[MAXN<<2]; 27 ll sum[MAXN<<2],ans; 28 vector <int> vec[MAXN]; 29 inline ll calc(ll k,ll b,int x,int y) {return ((ll)((ll)k*y+k*x+2*b)*((ll)y-x+1))/2;} 30 void pshd(int k,int l,int r,int mid) 31 { 32 sum[k<<1]+=calc(tagk[k],tagb[k],l,mid); 33 sum[k<<1|1]+=calc(tagk[k],tagb[k],mid+1,r); 34 tagk[k<<1]+=tagk[k],tagk[k<<1|1]+=tagk[k],tagb[k<<1]+=tagb[k],tagb[k<<1|1]+=tagb[k]; 35 tagk[k]=tagb[k]=0LL; 36 } 37 void mdf(int k,int l,int r,int a,int b,ll d,ll t) 38 { 39 if(l==a&&r==b) {tagb[k]+=t,tagk[k]+=d,sum[k]+=calc(d,t,l,r);return ;} 40 int mid=l+r>>1;if(tagb[k]!=0||tagk[k]!=0) pshd(k,l,r,mid); 41 if(b<=mid) mdf(k<<1,l,mid,a,b,d,t);else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,d,t); 42 else {mdf(k<<1,l,mid,a,mid,d,t);mdf(k<<1|1,mid+1,r,mid+1,b,d,t);} 43 sum[k]=sum[k<<1]+sum[k<<1|1]; 44 } 45 ll query(int k,int l,int r,int a,int b) 46 { 47 if(l==a&&r==b) return sum[k]; 48 int mid=l+r>>1;if(tagb[k]!=0||tagk[k]!=0) pshd(k,l,r,mid); 49 if(b<=mid) return query(k<<1,l,mid,a,b); 50 else if(a>mid) return query(k<<1|1,mid+1,r,a,b); 51 else return query(k<<1,l,mid,a,mid)+query(k<<1|1,mid+1,r,mid+1,b); 52 } 53 void work(int x) 54 { 55 int t,las=0,pos;rep(i,1,vec[x].size()-1) 56 { 57 t=vec[x][i],pos=las-(t-vec[x][i-1])+1; 58 ans+=query(1,0,N,pos+n,las+n); 59 mdf(1,0,N,pos+n+1,las+n+1,1,-pos-n); 60 if(las+n+2<=N) mdf(1,0,N,las+n+2,N,0,las-pos+1); 61 las=pos+1; 62 } 63 las=0;rep(i,1,vec[x].size()-1) 64 { 65 t=vec[x][i],pos=las-(t-vec[x][i-1])+1; 66 mdf(1,0,N,pos+n+1,las+n+1,-1,pos+n); 67 if(las+n+2<=N) mdf(1,0,N,las+n+2,N,0,pos-las-1); 68 las=pos+1; 69 } 70 } 71 int main() 72 { 73 n=read(),N=(n<<1)+5,tp=read();rep(i,1,n) {g[i]=read();if(!hsh[g[i]]) hsh[g[i]]=++m;} 74 rep(i,1,m) pb(i,0);rep(i,1,n) pb(hsh[g[i]],i);rep(i,1,m) pb(i,n+1); 75 rep(i,1,m) work(i);printf("%lld\n",ans); 76 }
View Code