zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    解决跨域问题的后端解决方案
    java-反射
    验证接口实现类对于接口中所有方法是否都要重写?
    完成Triangle时遇到的问题
    刚知道的一种算法
    完成ATM编程练习题时遇到的问题
    完成Account编程练习遇到的问题
    完成StopWatch编程练习题时遇到的一些问题
    Window环境下Java备份和恢复Mysql数据
    IDEA导入项目不下载依赖问题
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15191337.html
Copyright © 2011-2022 走看看