[hdu7099]Just Another Data Structure Problem

不难发现,问题即求满足以下条件的$(i,j)$对数:

1.$1le i<jle n$且$a_{i}=a_{j}$

2.$min_{ile kle j}y_{k}ge l$且$max_{ile kle j}y_{k}le r$

先考虑条件1,枚举$1le xle n$,并对满足$a_{i}=x$的$i$个数$cnt$分类讨论:

1.若$cntle B$(其中$B$为常数),那么$a_{i}=a_{j}=x$的区间个数和(指对所有这样的$x$)不超过$nB$,暴力预处理出此类区间$y_{i}$的最小值和最大值,即变为一个二维数点的问题

关于这个二维数点,注意到点初始给定且条件只有一边,因此对其中一维使用扫描线处理,那么另外一维即变为支持单点修改和区间查询

由于有$o(nB)$次修改和$o(m)$次查询,为了均摊可以采取多层分块的结构,假设分$t$层,则修改和查询的复杂度分别为$o(nBt)$和$o(mn^{frac{1}{t}}t)$(取$t=2$即为直接分块,取$t=log_{2}n$即为线段树)

2.若$cnt>B$,那么这类$x$不超过$frac{n}{B}$个,对应的$i$将序列划分若干段,并求出每一段$y_{i}$的最大值和最小值,注意到我们仅关心于$l,r$和这些最小值和最大值的关系,因此只有$o(cnt)$个本质不同的位置

由此使用莫队,问题即是要维护被包含的段长度(和和平方和),为了做到线性可以使用回滚莫队+链表,复杂度即$o(cntsqrt{m}+m)$,那么总复杂度为$o(nsqrt{m}+frac{nm}{B})$

另外,为了去掉其中的$log$,具体实现是可能要借助基数排序等操作,可以参考代码

取$B=sqrt{m}$和$t=3$即可,时间复杂度为$o(nsqrt{m}+mn^{frac{1}{3}})$,可以通过

(由于常数问题,取$B=4sqrt{m}$更优,另外为了实现方便代码中取了$t=2$)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 #define M 1000005
  5 #define ll long long
  6 #define pii pair<int,int>
  7 #define fi first
  8 #define se second
  9 struct Data{
 10     int l,r,id;
 11     bool operator < (const Data &k)const{
 12         return ((l<k.l)||(l==k.l)&&(r<k.r));
 13     }
 14 }Q[M];
 15 vector<int>v[N];
 16 int n,m,B,x,P[N];
 17 ll ans[M];
 18 namespace ST{
 19     int lg[N],mn[N][20],mx[N][20];
 20     void init(){
 21         lg[0]=-1;
 22         for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
 23         for(int i=1;i<=n;i++)mn[i][0]=mx[i][0]=P[i];
 24         for(int i=n;i;i--)
 25             for(int j=1;j<20;j++){
 26                 mn[i][j]=min(mn[i][j-1],mn[min(i+(1<<j-1),n)][j-1]);
 27                 mx[i][j]=max(mx[i][j-1],mx[min(i+(1<<j-1),n)][j-1]);
 28             }
 29     }
 30     int get_min(int l,int r){
 31         int m=lg[r-l+1];
 32         return min(mn[l][m],mn[r-(1<<m)+1][m]);
 33     }
 34     int get_max(int l,int r){
 35         int m=lg[r-l+1];
 36         return max(mx[l][m],mx[r-(1<<m)+1][m]);
 37     }
 38 }
 39 namespace Subtask1{
 40     int f[N],sum[N];
 41     vector<int>V[N];
 42     void update(int k){
 43         f[k]++,sum[k>>8]++;
 44     }
 45     int query(int k){
 46         int ans=0;
 47         for(int i=0;i<(k>>8);i++)ans+=sum[i];
 48         for(int i=((k>>8)<<8);i<=k;i++)ans+=f[i];
 49         return ans;
 50     }
 51     void calc(){
 52         for(int i=1;i<=n;i++)
 53             if (v[i].size()<=B){
 54                 for(int x=0;x<v[i].size();x++)
 55                     for(int y=x+1;y<v[i].size();y++){
 56                         int mn=ST::get_min(v[i][x],v[i][y]);
 57                         V[mn].push_back(ST::get_max(v[i][x],v[i][y]));
 58                     }
 59             }
 60         for(int i=n,k=m;i;i--){
 61             for(int j=0;j<V[i].size();j++)update(V[i][j]);
 62             while ((k)&&(Q[k].l==i)){
 63                 ans[Q[k].id]+=query(Q[k].r);
 64                 k--;
 65             }
 66         }
 67     }
 68 }
 69 namespace Subtask2{
 70     vector<int>V[N];
 71     int sz,cnt,K,l,r,mn[N],mx[N],vis[N],id[N],pos[N],L0[N],L1[N],R0[N],R1[N],L[N],R[N],mnV[N];
 72     ll Ans[N];
 73     void init(){
 74         Ans[0]=0;
 75         memset(vis,0,sizeof(vis));
 76         memset(L,0,sizeof(L));
 77         memset(R,0,sizeof(R));
 78     }
 79     void check_add(int k){
 80         if ((vis[k])&&(vis[k+1])){
 81             Ans[0]+=(ll)(k-L[k]+1)*(R[k+1]-k);
 82             R[L[k]]=R[k+1],L[R[k+1]]=L[k];
 83         }
 84     }
 85     void check_del(int k){
 86         if ((vis[k])&&(vis[k+1])){
 87             R[L[k]]=k,L[R[k+1]]=k+1;
 88             Ans[0]-=(ll)(k-L[k]+1)*(R[k+1]-k);
 89         }
 90     }
 91     void add(int k){
 92         vis[k]=1,L[k]=R[k]=k,Ans[0]++;
 93         check_add(k-1),check_add(k);
 94     }
 95     void del(int k){
 96         check_del(k-1),check_del(k);
 97         vis[k]=L[k]=R[k]=0,Ans[0]--;
 98     }
 99     void addl(){
100         if ((L0[l])&&(mx[L0[l]]<=pos[r]))del(L0[l]);
101         if ((L1[l])&&(mx[L1[l]]<=pos[r]))del(L1[l]);
102         l++;
103     }
104     void decl(){
105         l--;
106         if ((L0[l])&&(mx[L0[l]]<=pos[r]))add(L0[l]);
107         if ((L1[l])&&(mx[L1[l]]<=pos[r]))add(L1[l]);
108     }
109     void addr(){
110         r++;
111         if ((R0[r])&&(pos[l]<=mn[R0[r]]))add(R0[r]);
112         if ((R1[r])&&(pos[l]<=mn[R1[r]]))add(R1[r]);
113     } 
114     void decr(){
115         if ((R0[r])&&(pos[l]<=mn[R0[r]]))del(R0[r]);
116         if ((R1[r])&&(pos[l]<=mn[R1[r]]))del(R1[r]);
117         r--;
118     }
119     void calc(int k){
120         sz=v[k].size(),cnt=0;
121         memset(vis,0,sizeof(vis));
122         memset(L0,0,sizeof(L0));
123         memset(L1,0,sizeof(L1));
124         memset(R0,0,sizeof(R0));
125         memset(R1,0,sizeof(R1));
126         for(int i=1;i<sz;i++){
127             mn[i]=ST::get_min(v[k][i-1],v[k][i]);
128             mx[i]=ST::get_max(v[k][i-1],v[k][i]);
129             vis[mn[i]]=vis[mx[i]]=1;
130         }
131         for(int i=1;i<=n;i++){
132             if (vis[i])pos[++cnt]=i;
133             id[i]=cnt;
134         }
135         for(int i=1;i<sz;i++){
136             if (!L0[id[mn[i]]])L0[id[mn[i]]]=i;
137             else L1[id[mn[i]]]=i;
138             if (!R0[id[mx[i]]])R0[id[mx[i]]]=i;
139             else R1[id[mx[i]]]=i;
140         }
141         K=max(cnt/B,1);
142         for(int i=0,k=1;i*K<cnt;i++){
143             init(); 
144             int st=i*K+1,ed=min((i+1)*K,cnt);
145             for(int j=st;j<=cnt;j++){
146                 mnV[j]=0x3f3f3f3f;
147                 V[j].clear();
148             }
149             while ((k<=m)&&(Q[k].l<=pos[ed])){
150                 mnV[id[Q[k].r]]=min(mnV[id[Q[k].r]],id[Q[k].l-1]+1);
151                 V[id[Q[k].r]].push_back(k);
152                 k++;
153             }
154             for(int j=st;j<ed;j++){
155                 l=j+1,r=j,Ans[0]=Ans[j+1]=0;
156                 while (mnV[j]<l){
157                     decl();
158                     Ans[l]=Ans[0];
159                 }
160                 for(int k=0;k<V[j].size();k++)ans[Q[V[j][k]].id]+=Ans[id[Q[V[j][k]].l-1]+1];
161                 while (l<=j)addl();
162             } 
163             l=ed,r=ed-1,Ans[0]=0;
164             for(int j=ed;j<=cnt;j++){
165                 addr();
166                 Ans[l]=Ans[0];
167                 while (mnV[j]<l){
168                     decl();
169                     Ans[l]=Ans[0];
170                 }
171                 for(int k=0;k<V[j].size();k++)ans[Q[V[j][k]].id]+=Ans[id[Q[V[j][k]].l-1]+1];
172                 while (l<ed)addl();
173                 Ans[0]=Ans[l];
174             }
175         }
176     }
177     void calc(){
178         for(int i=1;i<=n;i++)
179             if (v[i].size()>B)calc(i);
180     }
181 } 
182 int main(){
183     ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
184     cin>>n>>m;
185     B=4*(int)sqrt(m);
186     for(int i=1;i<=n;i++){
187         cin>>x;
188         v[x].push_back(i);
189     }
190     for(int i=1;i<=n;i++)cin>>P[i];
191     for(int i=1;i<=m;i++){
192         cin>>Q[i].l>>Q[i].r;
193         Q[i].id=i;
194     }
195     sort(Q+1,Q+m+1);
196     ST::init();
197     Subtask1::calc();
198     Subtask2::calc();
199     for(int i=1;i<=m;i++)cout<<ans[i]<<'
';
200     return 0;
201 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/15191337.html