• cogs 2320. [HZOI 2015]聪聪的世界题解


    2320. [HZOI 2015]聪聪的世界

    时间限制:6 s   内存限制:512 MB

    【题目描述】

    背景:

    聪聪的性取向有问题。

    题目描述:

    聪聪遇到了一个难题:

    给出一个序列a1…an,完成以下操作:

    1  x 询问从x向左数第一个<ax的数;

    2  x 询问从x向左数第一个>ax的数;

    3  x 询问从x向右数第一个<ax的数;

    4  x 询问从x向右数第一个>ax的数;

    5  x y 交换ax与ay;

    6  x y w 给ax…ay加上w;

    7  x y w 给ax…ay减去w。

    聪聪急切的想知道答案,因为他完成任务后就可以迎娶高富帅,出任CEO,走上人生巅峰,成为人生赢家!

    请你帮帮他。

    【输入格式】

    第一行 n,m。

    第二行 a1…an。

    第三行到m+2行为以上七个操作。

    【输出格式】

    对于每个op>=1且op<=4输出一行表示答案,无解输出-1。

    【样例输入】

    5 5

    8 2 0 0 9

    1 2

    5 1 3

    7 1 3 1

    4 2

    1 1

    【样例输出】

    -1

    7

    -1

    【提示】

    10%  n,m<=10000

    40%  n,m<=100000

    100%  n,m<=1000000

    对于所有输入的数保证在[0,10^9]范围内

      学长们出的题造的孽啊,貌似打法很多,我在这里只讲一下线段树解法。

      首先先膜拜一下     神利·代目   stdafx.h,两位学长,我是在他们的引导下想出的O(log)时间复杂度内完成前4个操作的。

      因为这四个操作本质一样,因此我们就只讲第一种操作。

      请读者自己先思考5~10分钟,看看能否相出log复杂度的前四种操作打法,提醒一下,从根节点边向下边二分不靠谱。

      开讲了,首先,线段树是一棵完全二叉树,因此它满足一个规律,兄弟节点的编号亦或1就是他自己,而它自己的编号/2就是他父亲的编号,因此我们完全可以用这个性质从下向上攀爬,再利用这个性质从上向下攀爬。

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<cmath>
      8 using namespace std;
      9 long long n,m;
     10 struct no{
     11     long long left,right;
     12     long long mid,mn;
     13     long long mx,lazy;
     14 }node[4000004];
     15 long long a[1000005];
     16 long long dl[1000005];
     17 void build(long long left,long long right,long long x){
     18     node[x].left=left;
     19     node[x].right=right;
     20     if(left==right)
     21     {
     22         dl[left]=x;
     23         node[x].mn=node[x].mx=a[left];
     24         return;
     25     }
     26     long long mid=(left+right)/2;
     27     node[x].mid=mid;
     28     build(left,mid,2*x);
     29     build(mid+1,right,2*x+1);
     30     node[x].mx=max(node[2*x].mx,node[2*x+1].mx);
     31     node[x].mn=min(node[x*2].mn,node[2*x+1].mn);
     32 }
     33 void pushdown(long long x){
     34     if(node[x].lazy)
     35     {
     36         node[2*x].lazy+=node[x].lazy;
     37         node[2*x+1].lazy+=node[x].lazy;
     38         node[2*x].mx+=node[x].lazy;
     39         node[2*x+1].mx+=node[x].lazy;
     40         node[x*2].mn+=node[x].lazy;
     41         node[2*x+1].mn+=node[x].lazy;
     42         node[x].lazy=0;
     43     }
     44 }
     45 long long get(long long left,long long right,long long x){
     46     if(node[x].left==node[x].right)
     47     {
     48         return node[x].mx;
     49     }
     50     pushdown(x);
     51     long long mid=node[x].mid;
     52     if(right<=node[x].mid)
     53         return get(left,right,2*x);
     54     else
     55         return get(left,right,2*x+1);
     56 }
     57 void change(long long left,long long right,long long x,long long z){
     58     if(node[x].left==node[x].right)
     59     {
     60         node[x].mn=z;
     61         node[x].mx=z;
     62         return;
     63     }
     64     pushdown(x);
     65     long long mid=node[x].mid;
     66     if(right<=node[x].mid)
     67         change(left,right,2*x,z);
     68     else
     69         change(left,right,2*x+1,z);
     70     node[x].mx=max(node[2*x].mx,node[2*x+1].mx);
     71     node[x].mn=min(node[2*x].mn,node[1+2*x].mn);
     72 }
     73 void add(long long left,long long right,long long x,long long z){
     74     if(node[x].left==left&&node[x].right==right)
     75     {
     76         node[x].mx+=z;
     77         node[x].mn+=z;
     78         node[x].lazy+=z;
     79         return;
     80     }
     81     pushdown(x);
     82     long long mid=node[x].mid;
     83     if(right<=mid)
     84         add(left,right,2*x,z);
     85     else if(left>mid)
     86         add(left,right,2*x+1,z);
     87     else
     88         add(left,mid,2*x,z),add(mid+1,right,2*x+1,z);
     89     node[x].mx=max(node[2*x].mx,node[2*x+1].mx);
     90     node[x].mn=min(node[x*2].mn,node[2*x+1].mn);
     91 }
     92 long long que_ls(long long x,long long z,long long buf){
     93     if(node[x].left==node[x].right)
     94         return node[x].left;
     95     if(node[2*x+1].mn+buf+node[x].lazy<z)
     96         return que_ls(2*x+1,z,buf+node[x].lazy);
     97     else
     98         return que_ls(2*x,z,buf+node[x].lazy);
     99 }
    100 long long get_ls(long long x,long long z){
    101     if(x==1)
    102         return -1;
    103     if(!(x%2))
    104         return get_ls(x/2,z+node[x].lazy);
    105     else
    106     {
    107         if(z+node[x].lazy>node[x^1].mn)
    108             return que_ls(x^1,z+node[x].lazy,0);
    109         else
    110             return get_ls(x/2,z+node[x].lazy);
    111     }
    112 }
    113 long long que_lb(long long x,long long z,long long buf){
    114     if(node[x].left==node[x].right)
    115         return node[x].left;
    116     if(node[2*x+1].mx+buf+node[x].lazy>z)
    117         return que_lb(x*2+1,z,buf+node[x].lazy);
    118     else
    119         return que_lb(x*2,z,buf+node[x].lazy);
    120 }
    121 long long get_lb(long long x,long long z){
    122     if(x==1)
    123         return -1;
    124     if(!(x%2))
    125         return get_lb(x/2,z+node[x].lazy);
    126     else
    127     {
    128         if(z+node[x].lazy<node[x^1].mx)
    129             return que_lb(x^1,z+node[x].lazy,0);
    130         else
    131             return get_lb(x/2,z+node[x].lazy);
    132     }
    133 }
    134 long long que_rs(long long x,long long z,long long buf){
    135     if(node[x].left==node[x].right)
    136         return node[x].left;
    137     if(node[2*x].mn+buf+node[x].lazy<z)
    138         return que_rs(x*2,z,buf+node[x].lazy);
    139     else
    140         return que_rs(x*2+1,z,buf+node[x].lazy);
    141 }
    142 long long get_rs(long long x,long long z){
    143     if(x==1)
    144         return -1;
    145     if(x%2)
    146         return get_rs(x/2,z+node[x].lazy);
    147     else
    148     {
    149         if(z+node[x].lazy>node[x^1].mn)
    150             return que_rs(x^1,z+node[x].lazy,0);
    151         else
    152             return get_rs(x/2,z+node[x].lazy);
    153     }
    154 }
    155 long long que_rb(long long x,long long z,long long buf){
    156     if(node[x].left==node[x].right)
    157         return node[x].left;
    158     if(node[x*2].mx+buf+node[x].lazy>z)
    159         return que_rb(x*2,z,buf+node[x].lazy);
    160     else
    161         return que_rb(x*2+1,z,buf+node[x].lazy);
    162 }
    163 long long get_rb(long long x,long long z){
    164     if(x==1)
    165         return -1;
    166     if(x%2)
    167         return get_rb(x/2,z+node[x].lazy);
    168     else
    169     {
    170         if(z+node[x].lazy<node[x^1].mx)
    171             return que_rb(x^1,z+node[x].lazy,0);
    172         else
    173             return get_rb(x/2,z+node[x].lazy);
    174     }
    175 }
    176 int main(){
    177     freopen("ccsworld.in","r",stdin);
    178     freopen("ccsworld.out","w",stdout);
    179     scanf("%lld%lld",&n,&m);
    180     for(int i=1;i<=n;i++)
    181         scanf("%lld",&a[i]);
    182     build(1,n,1);
    183     for(int i=1;i<=m;i++)
    184     {
    185         long long tt;
    186         scanf("%lld",&tt);
    187         if(tt==1)
    188         {
    189             long long x;
    190             scanf("%lld",&x);
    191             long long y=get_ls(dl[x],node[dl[x]].mx-node[dl[x]].lazy);
    192             if(y!=-1) printf("%lld
    ",get(y,y,1));
    193             else printf("%lld
    ",y);
    194         }
    195         if(tt==2)
    196         {
    197             long long x;
    198             scanf("%lld",&x);
    199             long long y=get_lb(dl[x],node[dl[x]].mx-node[dl[x]].lazy);
    200             if(y!=-1) printf("%lld
    ",get(y,y,1));
    201             else printf("%lld
    ",y);
    202         }
    203         if(tt==3)
    204         {
    205             long long x;
    206             scanf("%lld",&x);
    207             long long y=get_rs(dl[x],node[dl[x]].mx-node[dl[x]].lazy);
    208             if(y!=-1) printf("%lld
    ",get(y,y,1));
    209             else printf("%lld
    ",y);
    210         }
    211         if(tt==4)
    212         {
    213             long long x;
    214             scanf("%lld",&x);
    215             long long y=get_rb(dl[x],node[dl[x]].mx-node[dl[x]].lazy);
    216             if(y!=-1) printf("%lld
    ",get(y,y,1));
    217             else  printf("%lld
    ",y);
    218         }
    219         if(tt==5)
    220         {
    221             long long x,y;
    222             scanf("%lld%lld",&x,&y);
    223             long long xx,yy;
    224             xx=get(x,x,1);
    225             yy=get(y,y,1);
    226             change(x,x,1,yy);
    227             change(y,y,1,xx);
    228         }
    229         if(tt==6)
    230         {
    231             long long x,y,z;
    232             scanf("%lld%lld%lld",&x,&y,&z);
    233             add(x,y,1,z);
    234         }
    235         if(tt==7)
    236         {
    237             long long x,y,z;
    238             scanf("%lld%lld%lld",&x,&y,&z);
    239             add(x,y,1,0-z);
    240         }
    241     }
    242     //while(1);
    243     return 0;
    244 }
    一份长达5k的代码,慎入

      因此,我们大可开个数组存下每个叶节点的编号,便于查找,然后就从我们询问的叶节点向上查找,如果当前位置为右子树,那么就看一下他的兄弟的最小值是否比它小,如果不是,那么继续向上爬,如果是,我们就从他的兄弟节点向下爬。如果当前位置是左子树,我们就得接着向上爬了,他的右子树是不满足条件的,因为本题有区间操作,所以lazy数组就成了一个让人头痛的东西,让我们来慢慢分析。

      首先我向上爬时路径上的lazy是影响的,因为我们都是从叶节点向上爬,因此叶节点的数值是最晚更新的,因此向上爬的lazy是一定要加上的,那么有人可能回去问了,有可能之前还有区间操作只是没下放呢,这就不必担心了,因为如果他没得到lazy,他的兄弟一定也没得到,两者抵消。

      其次,向下爬的lazy也是会影响的,因为我们要的是最靠近x的叶节点,因此我们应采用先右后左的方法,如果右子树的最小值比上面那步传下来的参数小,就搜右子树,左子树就不必管了,而lazy也是需要一直跟着下放,原理见上。

      我们最终传回来的值并不是当前节点的值,因为上面的值可能还没传下来,因此我们传的应当是它的位置,再从根节点向下搞也就是单点查询了。

      至于其他三个操作,请读者自己思考并实现。

      打完代码后提交,全WA,被QTY2001神犇提醒,没开long long。交完就A了,没啥坑点,主要是码力,被教练员吐槽代码能力弱的我都能在一小时之内搞掉,这道题的难度也是没谁了。这或许就是他只有3星的原因吧。

  • 相关阅读:
    maven报错【Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of】
    Srping框架中使用@query注解实现复杂查询
    FreeMarker自定义TemplateDirectiveModel
    SpringMVC和Freemarker整合,带自定义标签的使用方法
    关于FreeMarker自定义TemplateDirectiveModel
    滑块验证码【插件待研究】
    注册页面 注册码【欠缺较多 待完善】
    IO流-文件的写入和读取
    Date、String、Calendar相互转化
    Runtime类
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7296123.html
Copyright © 2020-2023  润新知