zoukankan      html  css  js  c++  java
  • bzoj4094 && luogu3097 最优挤奶

    题目大意:
    给定n个点排成一排,每个点有一个点权,有m次修改,每次改变某个点的点权并将最大点独立集计入答案,输出最终的答案


    其中(nle 40000 , mle 50000)

    QWQ说实话,一开始看这个题,没啥思路呀

    后来看了题解才知道是线段树

    我们考虑对一个区间,我们只需要关心左右节点是否取,就可以从小的区间更新大区间。
    从而实现线段树的区间合并了

    QWQ我们定义
    (f[i].both)表示左右边界都取
    (f[i].left)表示只取左边界
    (f[i].right)表示只取右边界
    (f[i].neither)表示左右边界都不取

    对于每种情况,我们分开讨论

    首先定义(l=2*root,r=2*root+1)
    对于(f[root].both)
    (f[root].both=max(f[l].left+max(f[r].both,f[r].right),f[l].both+f[r].right);)
    也就是如果左边只取左,右边可以都取或者只取右
    如果左边都取,那么右边只能取右了(因为中间的左右区间的交界处也是不能同时取到的)

    对于(f[root].right,f[root].left)

    (f[root].left=max(f[l].left+max(f[r].neither,f[r].left),f[l].both+f[r].neither);)
    (f[root].right=max(f[l].neither+max(f[r].right,f[r].both),f[l].right+f[r].right);)

    同样的方法,处理一下

    而对于(f[root].neither)

    (f[root].neither=max(max(f[l].neither+f[r].neither,f[l].right+f[r].neither),f[r].left+f[l].neither))

    然后考虑更新的部分话

    将一个点权修改也就是重新更新那个节点的(f[root].both),然后将其他的清零。
    最后更新就行

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<vector>
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 40010;
    
    struct Node{
        int left,right,both,neither;
    };
    
    Node f[4*maxn];
    int n,a[maxn];
    int m;
    long long ans;
    
    void up(int root)
    {
        int l = 2*root,r=2*root+1;
        f[root].both=max(f[l].left+max(f[r].both,f[r].right),f[l].both+f[r].right);
        f[root].left=max(f[l].left+max(f[r].neither,f[r].left),f[l].both+f[r].neither);
        f[root].right=max(f[l].neither+max(f[r].right,f[r].both),f[l].right+f[r].right);
        f[root].neither=max(max(f[l].neither+f[r].neither,f[l].right+f[r].neither),f[r].left+f[l].neither);
    }
    
    void build(int root,int l,int r)
    {
        if (l==r)
        {
            f[root].left=f[root].right=f[root].neither=0;
            f[root].both=a[l];
            return;
        }
        int mid = (l+r) >> 1;
        build(2*root,l,mid);
        build(2*root+1,mid+1,r);
        up(root);
    }
    
    void update(int root,int l,int r,int x,int p)
    {
        if (l==r)
        {
            f[root].left=f[root].right=f[root].neither=0;
            f[root].both=p;
            return;
        }
        int mid =(l+r) >> 1;
        if (x<=mid) update(2*root,l,mid,x,p);
        if (x>mid) update(2*root+1,mid+1,r,x,p);
        up(root);	
    }
    
    int main()
    {
      n=read();m=read();
      for (int i=1;i<=n;i++) a[i]=read();
      build(1,1,n);
      for (int i=1;i<=m;i++)
      {
      	int day,x;
      	day=read(),x=read();
      	update(1,1,n,day,x);
      	long long tmp=max(f[1].left,max(f[1].right,max(f[1].both,f[1].neither)));
      	ans+=tmp;
      }
      cout<<ans<<endl;
      return 0;
    }
    
    
  • 相关阅读:
    nginx配置zabbix下setup.php(web页面)无法显示,浏览器无法打开
    CentOS release 6.5下jdk1.7升级到1.8
    tcp流量控制
    图像处理服务器
    muduo rpc protobuf 实现学习
    p2p nat 穿透原理
    博客-livevent-stl-cpp-nginx
    使用eventfd创建一个用于事件通知的文件描述符
    多线程设计的类的思考!
    ftp协议服务器与tinyhttp服务demo
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160677.html
Copyright © 2011-2022 走看看