BZOJ 3221 [Codechef FEB13] Obserbing the tree树上询问 树链剖分 主席树维护区间加等差数列

题目大意:给出一棵树,每个结点初始均为0,要求支持以下操作:路径加等差数列,询问路径上结点权值和,回到之前的某个版本,强制在线。

调到吐血。

很明显可以看出需要树链剖分+主席树来解决,由于需要在主席树上区间修改所以标记永久化。
区间维护等差数列需要在每个结点上维护 首项 和 公差。
树链剖分时在路径上加等差数列需要讨论,细节比较多,详见代码。
(我看错题了..注意回到某个版本并不舍弃在这之间的版本)

#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 150005
#define int long long
using namespace std;
typedef long long LL;
int time_clock,tot_time;
namespace Segment_Tree {
    struct Node {
        Node* ch[2];
        int sum,a0,d,l,r,ver;
        Node(Node* tmp=NULL) {
            if(tmp) {
                ch[0]=tmp->ch[0];
                ch[1]=tmp->ch[1];
                sum=tmp->sum;
                a0=tmp->a0;
                d=tmp->d;
                l=tmp->l;
                r=tmp->r;
                ver=tmp->ver;
            }
            else {
                ch[0]=ch[1]=NULL;
                sum=l=r=a0=d=ver=0;
            }
        }
        void* operator new(size_t) {
            static Node *C,*mempool;
            if(C==mempool) mempool=(C=new Node[1<<20])+(1<<20);
            return C++;
        }
    }*root[N];
    void init(Node*& o,int l,int r) {
        o=new Node();
        o->l=l, o->r=r;
        if(l==r) return ;
        int mid=l+r>>1;
        init(o->ch[0],l,mid), init(o->ch[1],mid+1,r);
        return ;
    }
    int query(Node* o,int l,int r) {
        int tmp=(2*o->a0+o->d*(l+r-2*o->l))*(r-l+1)/2;
        if(o->l==l && o->r==r) return o->sum+tmp;
        int mid=o->l+o->r>>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值