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

 

转载于:https://www.cnblogs.com/yyc-jack-0920/p/10166735.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值