珂朵莉树模板(ODT)

解决区间赋值 + 区间\(k\)次方和(数据随机)

#include<bits/stdc++.h>
#define IT set<Node>::iterator
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;

struct Node{
    int l, r;
    mutable ll v;
    bool operator < (const Node &p) const{
        return l < p.l;
    }
};
set<Node> s;

IT split(int pos){
    IT it = s.lower_bound(Node{pos,pos,0});
    if(it != s.end() && it->l == pos) return it;
    it--;
    int l = it->l, r = it->r;
    ll v = it->v;
    s.erase(it);
    s.insert(Node{l, pos-1, v});
    return s.insert(Node{pos, r, v}).first;
}
//split要先r+1, 再l
void update(int l, int r, ll v){
    IT rit = split(r+1), lit = split(l);
    s.erase(lit, rit);
    s.insert(Node{l, r, v});
}

ll fpow(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b &1)
            ans = ans * a % mod;
        a = a * a % mod;
        b /= 2;
    }
    return ans;
}

ll query(int l, int r, ll k){
    IT rit = split(r+1), lit = split(l);
    ll ans = 0;
    for(; lit != rit;lit++)
        ans += fpow(lit->v, k) * 1ll * (lit->r - lit->l);
    return ans;
}

int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    s.insert(Node{1, n, 0ll});
    int id, l, r;
    ll x;
    while(m--){
        scanf("%d%d%d%lld", &id, &l, &r, &x);
        if(id == 1)
            update(l, r, x);
        else
            printf("%lld\n", query(l, r, x));
    }
}
posted @ 2020-03-30 23:53  竹攸  阅读(151)  评论(0编辑  收藏  举报