首页 > 其他分享 >DOS Card (线段树)(hud杭电多校)

DOS Card (线段树)(hud杭电多校)

时间:2022-09-05 11:35:59浏览次数:97  
标签:hud a10 max a00 tr a1 a0 DOS Card

题目:

对序列 a,回答 q 次询问:

  • 给定长度至少为 4 的区间 [L,R],在区间内选择 1对 (ai,aj)(L≤i<j≤R)可以获取分数 (ai+aj)(ai−aj) ,计算选择 2 对可以获取的最大分数之和。

注意:你选择的 2 对共 4 个数中不能有重复的位置

思路:

  • 首先可以想到 选取的4个数 这 2种形式 大大小小, 大小大小, 
  • 于是从 这里入手 利用线段树, 维护信息 这里用 0 1 表示
  • 0,1,01,10,---------
  • 查询返回的值就就是 结构体 tree

具体看大佬的代码:杭电多校第二场 DOS Card - 0htoAi - 博客园 (cnblogs.com)

#include <bits/stdc++.h>
static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
template<typename item>
inline void read(register item &x)
{
    bool flag=false;
    x=0;register char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
        flag=true;
        c=getchar();
    }
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    if(flag)
    x=-x;
}
static char cc[10000];
template<typename item>
inline void print(register item x)
{ 
    if(x==0)
    {
        cc[0]='0';
        putchar(cc[0]);
        return;
    }
    if(x<0)
    {
        cc[0]='-';
        putchar(cc[0]);
        x=-x;
    }
    register long long len=0;
    while(x)cc[len++]=x%10+'0',x/=10;
    while(len--)putchar(cc[len]);
}
long long max(long long a,long long b)
{
    return a>b?a:b;
}
const int MAXN=1e6+50;
struct Tree
{
    long long a1,a0,
    a11,a00,a10,a01,
    a010,a101,a100,a110,
    a1010,a1100;
}tr[MAXN];
Tree Merge(Tree x,Tree y)
{
    Tree z;
    //Len1:
    z.a0=max(x.a0,y.a0);
    z.a1=max(x.a1,y.a1);
    //Len2:
    z.a11=max(x.a11,max(x.a1+y.a1,y.a11));
    z.a00=max(x.a00,max(x.a0+y.a0,y.a00));
    z.a10=max(x.a10,max(x.a1+y.a0,y.a10));
    z.a01=max(x.a01,max(x.a0+y.a1,y.a01));
    //Len3:
    z.a010=max(x.a010,max(x.a01+y.a0,max(x.a0+y.a10,y.a010)));
    z.a101=max(x.a101,max(x.a10+y.a1,max(x.a1+y.a01,y.a101)));
    z.a100=max(x.a100,max(x.a10+y.a0,max(x.a1+y.a00,y.a100)));
    z.a110=max(x.a110,max(x.a11+y.a0,max(x.a1+y.a10,y.a110)));
    //Len4:
    z.a1010=max(x.a1010,max(x.a101+y.a0,max(x.a10+y.a10,max(x.a1+y.a010,y.a1010))));
    z.a1100=max(x.a1100,max(x.a110+y.a0,max(x.a11+y.a00,max(x.a1+y.a100,y.a1100)))); 
    return z;
}
long long a[MAXN];
void Build(int u,int l,int r)
{
    if(l==r)
    {
        tr[u].a0=-a[l];
        tr[u].a1=a[l];
        tr[u].a00=tr[u].a01=tr[u].a10=tr[u].a11=-1e18;
        tr[u].a010=tr[u].a100=tr[u].a101=tr[u].a110=-1e18;
        tr[u].a1010=tr[u].a1100=-1e18;
        return;
    }
    int Mid=l+r>>1;
    Build(u<<1,l,Mid);
    Build(u<<1|1,Mid+1,r);
    tr[u]=Merge(tr[u<<1],tr[u<<1|1]);
}

Tree Query(int u,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return tr[u];
    }
    int Mid=l+r>>1;
    if((x<=Mid)&&(y>=Mid+1))
    {
        return Merge(Query(u<<1,l,Mid,x,y),Query(u<<1|1,Mid+1,r,x,y));
    }
    if(x<=Mid)
    {
        return Query(u<<1,l,Mid,x,y);
    }
    if(y>=Mid+1)
    {
        return Query(u<<1|1,Mid+1,r,x,y);
    }
}
int N,Q;
int main()
{
    int T;
    read(T);
    while(T--)
    {
        read(N);
        read(Q);
        for(int i=1;i<=N;i++)
        {
            read(a[i]);
            a[i]*=a[i];
        }
        Build(1,1,N);
        while(Q--)
        {
            int l,r;
            read(l);
            read(r);
            Tree ans=Query(1,1,N,l,r);
            print(max(ans.a1010,ans.a1100));
            putchar('\n');
        }    
    }
    
    fwrite(obuf,p3-obuf,1,stdout);
}
View Code

后记:

  • 入手点一定要找好, 当时想到了 1100,1010, 但是没有深入,就过了
  • 线段树的功能细细体会

 

标签:hud,a10,max,a00,tr,a1,a0,DOS,Card
From: https://www.cnblogs.com/Lamboofhome/p/16657508.html

相关文章

  • copy (倒叙离线+bitset+^特性) (hud 2022多校 2)
    题目:给定一个序列 a1,a2,…,an,共有 q 次操作,每次操作有两种类型:操作1(1,l,r) 表示复制区间 [l,r] 的内容,在区间 [l,r]的末尾处插入这段内容。操作2(2,x) 询问......
  • 预科知识3-基本的Dos命令
    打开CMD的方式:​1.开始+系统+命令提示符​2.win键+R输入cmd打开控制台(推荐使用)​3.在任意的文件夹里面,按住shift+鼠标右键点击,在此处打开powershell窗......
  • 在cmd运行窗口中输入DOS命令netstat,即可查看电脑的tcp连接。
    如何查看tcp连接_百度知道 https://zhidao.baidu.com/question/202977646.html在cmd运行窗口中输入DOS命令netstat,即可查看电脑的tcp连接。具体操作请参照以下步骤。1......
  • 常用的Dos命令
    常用的Dos命令盘符切换  英文模式 盘符+:查看当前目录下的所有文件 dir 切换目录 cd(change directory)cd.. 返回上一级清理屏幕 cls (clearscre......
  • 常见的Dos命令
    常见的Dos命令1.打开CMD的方式开始菜单+Windows系统+命令提示符。Win+R输入CMD打开控制台(推荐使用)。在任意文件夹下,按住Shift键+鼠标右键+打开命令行......
  • 常用的dos命令
    ctrl+c复制ctrl+v粘贴ctrl+s保存ctrl+z撤销ctrl+x剪切java-version查看Java是否安装成功常用的dos命令 #常盘切换符 #查看当前目录下所有文件dir #切换目录......
  • 数据湖三剑客 Hudi、Delta、Iceberg 对比
    一、介绍在构建数据湖时,也许没有比数据格式存储更具有意义的决定。其结果将对其性能、可用性和兼容性产生直接影响。通过简单地改变数据的存储格式,我们就可以解锁新的......
  • Dos 常用命令
    Dos常用命令   dir(大小写都可))查看当前路径下的内容D:\>dir驱动器D中的卷是Data卷的序列号是C06D-46EE​D:\的目录​2022/08/29 19:09  <DIR>......
  • 小复习:简单Dos命令
    1cd切盘符cdD: 2查看目录dir3切换目录cd/d C:\目录名注:参数是正斜杠/  目录是反斜杠\同盘直接cd目录名3cd..返回上一级4清理屏幕cls5退出exit5查......
  • Day02__Dos基础命令
    常用的Dos命令#盘符切换 D:#查看当前目录下的所有文件 dir#切换目录 cdD: cd/dD:(跨盘时) cd.. (返回上一级) cd+(地址名)(切换目录)#清理......