• 题解 P3372 【【模板】线段树 1】(珂朵莉树解法)


    这道题可以用珂朵莉树做,但是由于数据比较不随机,而我也没有手写一颗平衡树,所以就被卡掉了,只拿了70分


    珂朵莉树是一种基于平衡树的(伪)高效数据结构。

    它的核心操作是推平一段区间。

    简而言之,就是把之前的零零碎碎的都干掉,用一个美而饱满的大区间取代。

    然后我们更新操作和查询操作就暴力遍历一遍,统计一下和就可以了。


    Split操作

    1 inline set<node>::iterator split(int pos){
    2     set<node>::iterator it=s.lower_bound(node(pos));
    3     if(it!=s.end()&&it->l==pos)return it;
    4     --it;
    5     int L=it->l,R=it->r;long long V=it->v;
    6     s.erase(it),s.insert(node(L,pos-1,V));
    7     return s.insert(node(pos,R,V)).first;
    8 }

    split操作就是获得区间的迭代器。

    所以我们要先找到pos在哪里(也就是it)。

    然后把它拆掉,再合在一起。

    在这个过程中我们就可以拿到迭代器。(干什么等会说)


    Update操作

    1 inline void update(int l,int r,long long val=1){
    2     set<node>::iterator itl=split(l),itr=split(r+1);
    3     for(;itl!=itr;++itl)itl->v+=val;
    4 }

    现在刚才的split就派上用场了。

    我们现在相当于是获得了区间的两端(也是区间)。

    然后暴力遍历一下,给每个区间都打一个标记。


    Query操作

    1 inline long long query(int l,int r){
    2     set<node>::iterator itl=split(l),itr=split(r+1);
    3     long long ans=0;
    4     for(;itl!=itr;++itl)ans+=(itl->r-itl->l+1)*itl->v;
    5     return ans;
    6 }

    收集一下标记加在一起就可以了,思路和update一样。


    70分代码如下:

    3741ms 2368kb

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 namespace StandardIO{
      6 
      7     template<typename T>inline void read(T& x){
      8         x=0;T f=1;char c=getchar();
      9         for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
     10         for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
     11         x*=f;
     12     }
     13 
     14     template<typename T>inline void write(T x){
     15         if(x<0)putchar('-'),x*=-1;
     16         if(x>=10)write(x/10);
     17         putchar(x%10+'0');
     18     }
     19 
     20 }
     21 
     22 using namespace StandardIO;
     23 
     24 namespace ChthollyTree{
     25     
     26     struct Tree{
     27         private:
     28             struct node{
     29                 int l,r;mutable long long v;
     30                 node(int L,int R=-1,long long V=0):l(L),r(R),v(V){}
     31                 bool operator < (const node &o)const{
     32                     return l<o.l;
     33                 } 
     34             };
     35             set<node>s;
     36             
     37             inline set<node>::iterator split(int pos){
     38                 set<node>::iterator it=s.lower_bound(node(pos));
     39                 if(it!=s.end()&&it->l==pos)return it;
     40                 --it;
     41                 int L=it->l,R=it->r;long long V=it->v;
     42                 s.erase(it),s.insert(node(L,pos-1,V));
     43                 return s.insert(node(pos,R,V)).first;
     44             }
     45             
     46             inline void update(int l,int r,long long val=1){
     47                 set<node>::iterator itl=split(l),itr=split(r+1);
     48                 for(;itl!=itr;++itl)itl->v+=val;
     49             }
     50             
     51             inline long long query(int l,int r){
     52                 set<node>::iterator itl=split(l),itr=split(r+1);
     53                 long long ans=0;
     54                 for(;itl!=itr;++itl)ans+=(itl->r-itl->l+1)*itl->v;
     55                 return ans;
     56             }
     57             
     58         public:
     59             Tree(){}
     60             ~Tree(){}
     61             
     62             inline void Init(int n){
     63                 s.insert(node(1,n));
     64             }
     65             
     66             inline void Update(int l,int r,long long val){
     67                 update(l,r,val);
     68             }
     69             
     70             inline int Query(int l,int r){
     71                 return query(l,r); 
     72             }
     73     };
     74     
     75 }
     76 
     77 using namespace ChthollyTree;
     78 
     79 namespace Solve{
     80     
     81     const int N=100100;
     82     
     83     int n,m;
     84     int sum[N];
     85     Tree ljz;
     86     
     87     inline void solve(){
     88         read(n),read(m);
     89         ljz.Init(n);
     90         for(register int i=1;i<=n;++i){
     91             int tmp;read(tmp);
     92             sum[i]=sum[i-1]+tmp;
     93         } 
     94         while(m--){
     95             int op,x,y,z;
     96             read(op),read(x),read(y);
     97             if(op==1){
     98                 read(z);
     99                 ljz.Update(x,y,z);
    100             }else{
    101                 write(ljz.Query(x,y)+sum[y]-sum[x-1]),putchar('
    ');
    102             }
    103         }
    104     }
    105 
    106 }
    107 
    108 using namespace Solve;
    109 
    110 int main(){
    111     solve();
    112 }
  • 相关阅读:
    LeetCode-5. Longest Palindromic Substring(M)
    Python if else简洁写法,列表推导式,三目运算符写法
    Java GC机制
    int与integer的区别
    Java内存分配机制
    HashMap原理
    哈希表算法
    哈希
    java 三大框架面试题
    Java反射机制
  • 原文地址:https://www.cnblogs.com/ilverene/p/9846339.html
Copyright © 2020-2023  润新知