zoukankan      html  css  js  c++  java
  • 【模拟8.05】优美序列(线段树 分块 ST算法)

    如此显然的线段树,我又瞎了眼了

    事实上跟以前的奇袭很像.......

    只要满足公式maxn-minn(权值)==r-l即可

    所以可以考虑建两颗树,一棵节点维护位置,一棵权值,

    每次从一棵树树上查询信息,如果满足公式就停止,不然两颗树不断扩展区间

    当然也可以用ST啦(查询O(1)优于线段树)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<string>
     6 #include<set>
     7 #include<map>
     8 #include<vector>
     9 #include<cmath>
    10 #define int long long
    11 #define MAXN 100101
    12 using namespace std;
    13 char buffer[1<<20|1],*S,*T;
    14 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,1<<20|1,stdin),S==T))?EOF:*S++)
    15 int read()
    16 {
    17     int x=0;char c=getchar();
    18     while(c<'0'||c>'9')c=getchar();
    19     while(c>='0'&&c<='9')
    20     {
    21           x=(x<<1)+(x<<3)+(c^48);
    22           c=getchar();
    23     }
    24     return x;
    25 }
    26 int a[MAXN];
    27 int maxn,minn;
    28 int n,m;int binn[MAXN];
    29 int f[21][MAXN];int f_min[21][MAXN];//区间极值的最小位置,最大位置
    30 int wei[21][MAXN];int wei_min[21][MAXN];
    31 void work()
    32 { 
    33     int t=log(n)/log(2);
    34     for(int j=1;j<=t;++j)
    35     {
    36         for(int i=1;i<=(n+1-binn[j]);++i)
    37         {
    38             f[j][i]=max(f[j-1][i],f[j-1][i+binn[j-1]]);
    39             f_min[j][i]=min(f_min[j-1][i],f_min[j-1][i+binn[j-1]]);
    40             wei[j][i]=max(wei[j-1][i],wei[j-1][i+binn[j-1]]);
    41             wei_min[j][i]=min(wei_min[j-1][i],wei_min[j-1][i+binn[j-1]]);
    42         }
    43     }
    44 } 
    45 int maxn_wei,minn_wei;
    46 void RMB(int l,int r)
    47 {
    48     int t=log(r-l+1)/log(2);
    49     maxn_wei=max(f[t][l],f[t][r+1-binn[t]]);
    50     minn_wei=min(f_min[t][l],f_min[t][r+1-binn[t]]);
    51     return ;
    52 }
    53 
    54 void RMB_wei(int l,int r)
    55 {
    56     int t=log(r-l+1)/log(2);
    57     maxn=max(wei[t][l],wei[t][r+1-binn[t]]);
    58     minn=min(wei_min[t][l],wei_min[t][r+1-binn[t]]);
    59     return ;
    60 }
    61 signed main()
    62 {
    63      n=read();
    64      for(int i=1;i<=n;++i)
    65      {
    66          a[i]=read();
    67          f[0][a[i]]=i;f_min[0][a[i]]=i;
    68          wei[0][i]=a[i];wei_min[0][i]=a[i];
    69      }
    70      binn[0]=1;
    71      for(int i=1;i<=20;++i)binn[i]=(binn[i-1]<<1);
    72      work();
    73      m=read();
    74      for(int i=1;i<=m;++i)
    75      {
    76          int l,r;
    77          l=read();r=read();
    78          maxn=0;minn=0x7ffffffff;maxn_wei=r;minn_wei=l;
    79          while(maxn-minn!=maxn_wei-minn_wei)
    80          {
    81               RMB_wei(minn_wei,maxn_wei);
    82               RMB(minn,maxn);
    83          }
    84          printf("%lld %lld
    ",minn_wei,maxn_wei);
    85      }
    86 }
    80 超时

    100分:

    %%%%%skyh 分块思想碾爆tarjan正解

    因为每次区间不断扩展可能会扩展好多边,

    那么我们把区间分块,这样预处理出块与块的答案

    在实际查询中如果发现当前查询区间大于块的区间,那就可以判断是否用块跳跃

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<string>
      6 #include<set>
      7 #include<map>
      8 #include<vector>
      9 #include<cmath>
     10 #define int long long
     11 #define MAXN 100101
     12 using namespace std;
     13 int kuan[MAXN];int belong[MAXN];
     14 char buffer[1<<20|1],*S,*T;
     15 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,1<<20|1,stdin),S==T))?EOF:*S++)
     16 inline void read(int &x){x=0;
     17     register char c=getchar();
     18     while(c<'0'||c>'9')c=getchar();
     19     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=getchar();
     20 }
     21 int a[MAXN];
     22 int maxn,minn;int maxn_wei,minn_wei;
     23 int n,m;int binn[MAXN];
     24 int f[21][MAXN];int f_min[21][MAXN];//区间极值的最小位置,最大位置
     25 int wei[21][MAXN];int wei_min[21][MAXN];
     26 int ans_l[1000][1000];
     27 int ans_r[1000][1000];
     28 int tt,base;int Log[MAXN];
     29 void RMB(int l,int r)//通过权值查位置
     30 {
     31     int t=Log[r-l+1];
     32     maxn_wei=max(f[t][l],f[t][r+1-binn[t]]);
     33     minn_wei=min(f_min[t][l],f_min[t][r+1-binn[t]]);
     34     return ;
     35 }
     36 void RMB_wei(int l,int r)//通过位置察权值
     37 {
     38     int t=Log[r-l+1];
     39     maxn=max(wei[t][l],wei[t][r+1-binn[t]]);
     40     minn=min(wei_min[t][l],wei_min[t][r+1-binn[t]]);
     41     return ;
     42 }
     43 void work()
     44 { 
     45     int t=Log[n];
     46     for(int j=1;j<=t;++j)
     47     {
     48         for(int i=1;i<=(n+1-binn[j]);++i)
     49         {
     50             f[j][i]=max(f[j-1][i],f[j-1][i+binn[j-1]]);
     51             f_min[j][i]=min(f_min[j-1][i],f_min[j-1][i+binn[j-1]]);
     52             wei[j][i]=max(wei[j-1][i],wei[j-1][i+binn[j-1]]);
     53             wei_min[j][i]=min(wei_min[j-1][i],wei_min[j-1][i+binn[j-1]]);
     54         }
     55     }
     56     for(int i=1;i<base;++i)
     57     {
     58         for(int j=i+1;j<=base;++j)
     59         {
     60             int l=kuan[i],r=kuan[j];//位置查权值
     61             maxn=0;minn=0x7ffffffff;maxn_wei=r;minn_wei=l;
     62             while(maxn-minn!=maxn_wei-minn_wei)
     63             {
     64                  RMB_wei(minn_wei,maxn_wei);
     65                  RMB(minn,maxn);
     66             }   
     67             ans_l[i][j]=minn_wei;ans_r[i][j]=maxn_wei;
     68            // printf("ansl[%lld][%lld] i=%lld j=%lld
    ",minn_wei,maxn_wei,i,j);
     69         }
     70     }
     71 } 
     72 
     73 signed main()
     74 {
     75      read(n);
     76      tt=pow(n,0.66666);
     77      Log[0]=-1;for(register int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
     78      for(int i=1;i;++i)
     79      {
     80         if(i*tt>=n)
     81         {
     82            kuan[i]=n;
     83            base=i;
     84            break;
     85         }
     86         else
     87            kuan[i]=i*tt;
     88      }
     89      for(int i=1;i<=n;++i)
     90      {
     91          read(a[i]);
     92          f[0][a[i]]=i;f_min[0][a[i]]=i;
     93          wei[0][i]=a[i];wei_min[0][i]=a[i];
     94          belong[i]=((i-1)/tt)+1;
     95      }
     96      binn[0]=1;
     97      for(int i=1;i<=20;++i)binn[i]=(binn[i-1]<<1);
     98      work();
     99      read(m);
    100      for(int i=1;i<=m;++i)
    101      {
    102          int l,r;
    103          read(l);read(r);
    104          maxn=0;minn=0x7ffffffff;
    105          maxn_wei=r;minn_wei=l; 
    106          RMB_wei(minn_wei,maxn_wei);
    107          while(maxn-minn!=maxn_wei-minn_wei)
    108          {
    109               //printf("maxn=%lld minn=%lld maxn_wei=%lld minwei=%lld
    ",maxn,minn,maxn_wei,minn_wei);
    110               RMB(minn,maxn);
    111               int one=belong[minn_wei],two=belong[maxn_wei];
    112               //printf("one=%lld two=%lld
    ",one,two);
    113               if(two>one+1&&one-1!=0)
    114               {
    115                     if(ans_l[one][two-1]<=minn_wei&&ans_r[one][two-1]>=maxn_wei)
    116                     {
    117                          minn_wei=ans_l[one][two-1];
    118                          maxn_wei=ans_r[one][two-1];
    119                          //printf("min_wei=%lld ma_wei=%lld
    ",minn_wei,maxn_wei);
    120                     }
    121               }
    122               //printf("maxn=%lld minn=%lld maxn_wei=%lld minwei=%lld
    ",maxn,minn,maxn_wei,minn_wei);
    123               RMB_wei(minn_wei,maxn_wei);
    124               if(maxn-minn==maxn_wei-minn_wei)break;
    125          }
    126          printf("%lld %lld
    ",minn_wei,maxn_wei);
    127      }
    128 }
    %%%天皇
  • 相关阅读:
    268. Missing Number(LeetCode)
    Win7 发生验证错误 要求的函数不受支持
    下拉选择框的选项过滤
    金额小写带逗号处理
    Java将CST的时间字符串转换成需要的日期格式字符串
    MyEclipse部署项目报"Add Deployment". Invalid Subscription Level
    无法解析的DNS服务地址
    选择文件进行上传
    让button居中显示的的标签
    Mysql启动服务提示系统找不到指定的文件
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11312029.html
Copyright © 2011-2022 走看看