1. 程式人生 > >18寒假第五測

18寒假第五測

rotate ldb sequence == div img 什麽 splay pos

技術分享圖片

技術分享圖片

技術分享圖片

第一題 線段樹

樹狀數組存差b[i] = a[i]-a[i-1],反正是單點查詢,我為什麽沒想到。。。很傻的用線段樹

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define ll long long 
int n, m, a[maxn];
struct SegmentTree{
    struct node{
        ll sum;
        int lazy; 
    };
    node Tree[maxn << 2];
    
    #define ls l, m, v << 1
    #define
rs m+1, r, v << 1 | 1 void updata(int v){ Tree[v].sum = Tree[v << 1].sum + Tree[v << 1 | 1].sum; } void push_down(int l, int r, int v){ int m = (l + r) >> 1; Tree[v << 1].sum += Tree[v].lazy * (m - l + 1) * 1LL; Tree[v
<< 1].lazy += Tree[v].lazy; Tree[v << 1 | 1].sum += Tree[v].lazy * (r - m) * 1LL; Tree[v << 1 | 1].lazy += Tree[v].lazy; Tree[v].lazy = 0; } void build(int l = 1, int r = n, int v = 1){ if(l == r) Tree[v].sum = a[l], Tree[v].lazy = 0;
else { int m = (l + r) >> 1; build(ls); build(rs); updata(v); } } void modify(int x, int L, int R, int l = 1, int r = n, int v = 1){ if(l >= L && r <= R){ Tree[v].sum += x * (r - l + 1) * 1LL; Tree[v].lazy += x; } else { if(Tree[v].lazy) push_down(l, r, v); int m = (l + r) >> 1; if(L <= m)modify(x, L, R, ls); if(R > m)modify(x, L, R, rs); updata(v); } } ll query(int x,int l = 1, int r = n, int v = 1){ if(l == r)return Tree[v].sum; else { if(Tree[v].lazy) push_down(l, r, v); int m = (l + r) >> 1; if(x <= m) return query(x, ls); if(x > m)return query(x, rs); } } }; SegmentTree Tr; int main(){ freopen("bit.in","r",stdin); freopen("bit.out","w",stdout); cin>>n; for(int i = 1; i <= n; i++)scanf("%d", a + i); Tr.build(); cin>>m; for(int i = 1; i <= m; i++){ string opt; cin>>opt; if(opt[0] == m){ int l, r, val; scanf("%d%d%d",&l,&r,&val); Tr.modify(val, l, r); } else { int x; scanf("%d",&x); cout<<Tr.query(x)<<endl; } } }

第二題:一道巨惡心的線段樹取模,一般公式知道了就沒問題,但lazy乘起來是long long ,一堆人看了一晚上。。。第二天又忘了long long

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define ll long long 
int n, m, a[maxn];
int mod = 1000000007;
struct SegmentTree{
    struct node{
        ll sum,lazy[2];
    };
    node Tree[maxn << 2];
    
    #define ls l, m, v << 1
    #define rs m+1, r, v << 1 | 1
    
    void updata(int v){
        Tree[v].sum = ( Tree[v << 1].sum % mod + Tree[(v << 1) | 1].sum % mod ) % mod;
        
    }
    
    void push_down(int l, int r, int v){
        if(Tree[v].lazy[0] == 1 && Tree[v].lazy[1] == 0)return;
        int m = (l + r) >> 1;
        int A = Tree[v].lazy[0], B = Tree[v].lazy[1];
        modify(A, B, l, m, ls);
        modify(A, B, m+1, r, rs);        
        Tree[v].lazy[0] = 1, Tree[v].lazy[1] = 0;
    }
    void build(int l = 1, int r = n, int v = 1){
        if(l == r) Tree[v].sum = a[l], Tree[v].lazy[0] = 1, Tree[v].lazy[1] = 0;
        else {
            int m = (l + r) >> 1;
            build(ls);
            build(rs);
            updata(v);
            Tree[v].lazy[0] = 1, Tree[v].lazy[1] = 0;
        }
    }
    
    void modify(int A, int B, int L, int R, int l = 1, int r = n, int v = 1){
        if(l >= L && r <= R){
            ll q = Tree[v].sum;
            Tree[v].sum = (q * (A % mod) + 1LL * (B % mod) * (r - l + 1 )) % mod;
            ll olda = Tree[v].lazy[0], oldb = Tree[v].lazy[1];
            Tree[v].lazy[0] = A * olda % mod , Tree[v].lazy[1] = ( A * oldb + B )% mod;
            //printf("olda = %d A = %d newa = %d\n",olda,A, Tree[v].lazy[0]);
        }
        else {
            push_down(l, r, v);
            int m = (l + r) >> 1;
            if(L <= m)modify(A, B, L, R, ls);
            if(R > m)modify(A, B, L, R, rs);
            updata(v);
        }
        
    }
    
    ll query(int L,int R,int l = 1, int r = n, int v = 1){
        if(l >= L && r <= R)return Tree[v].sum ;
        else {
            push_down(l, r, v);
            int m = (l + r) >> 1;
            ll ans = 0;
            if(L <= m) ans = (ans + query(L, R, ls) % mod) % mod;
            if(R > m)ans = (ans % mod + query(L, R, rs)% mod) % mod;
            return ans;
        }
    }
};
SegmentTree Tr;
int main(){
    freopen("linear.in","r",stdin);
    freopen("linear.out","w",stdout);
    cin>>n;
    for(int i = 1; i <= n; i++)scanf("%d", a + i);
    Tr.build();
    cin>>m;
    for(int i = 1; i <= m; i++){
        string opt;
        cin>>opt;
        if(opt[0] == m){
            int l, r, A, B;
            scanf("%d%d%d%d",&l,&r,&A,&B);
            Tr.modify(A, B, l, r);
            
        }
        else {
            int l, r;
            scanf("%d%d",&l,&r);
            cout<<Tr.query(l, r)<<endl;
        }
    }
}

第三題 裸的splay扳子,很少找到卿學姐有這麽接地氣的板子,就搬過了,但splay的地方還是寫掛了。。。

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define ll long long 
int n, m, a[maxn], val[maxn];
struct SplayTree{
    int siz[maxn], fa[maxn], son[maxn][2];
    int tot, root;
    void update(int nd){
        siz[nd] = siz[son[nd][0]] + siz[son[nd][1]] + 1;
    }
    void init(){
        siz[0] = 0;
        tot = 0;
        root = build(0, 1, n);
    }
    int build(int f, int l,int r){
        
        if(l > r)return 0;
        int nd = ++tot;
        fa[nd] = f;
        int m = (l + r) >> 1;
        son[nd][0] = build(nd, l, m - 1);
        son[nd][1] = build(nd, m + 1, r);
        val[nd] = a[m];
        update(nd);
        //printf("nd = %d s[0] = %d, s[1] = %d, l = %d, r = %d val = %d\n",nd,son[nd][0],son[nd][1],l,r,val[nd]);
        return nd;
        
    }
    int find(int pos){
        int nd = root;
        while(1){
            int ls = siz[son[nd][0]];
            if(pos <= ls)nd = son[nd][0];
            else if(pos >= ls + 2){
                pos -= ls + 1;
                nd = son[nd][1];
            }
            else return nd;
            
        }
    }
    int query(int pos){
        return val[find(pos)];
    }
    void rotate(int x,int d){
        int y = fa[x];
        son[y][d^1] = son[x][d];
        if(son[x][d])fa[son[x][d]] = y;
        fa[x] = fa[y];
        if(fa[y]){
            if(y == son[fa[y]][d])son[fa[y]][d] = x;
            else son[fa[y]][d^1] = x;
        }
        son[x][d] = y, fa[y] = x;
        update(y), update(x);
    }
    void splay(int x,int target = 0){
        while(fa[x] != target){
            int y = fa[x];
            if(x == son[y][0]){
                if(fa[y] != target && y == son[fa[y]][0])
                    rotate(y, 1);
                rotate(x, 1);
            }
            else {
                if(fa[y] != target && y == son[fa[y]][1])
                    rotate(y, 0);
                rotate(x, 0);
            }
        }
        if(!target)root = x;
    }
    void erase(int pos){
        int lnd = find(pos - 1), rnd = find(pos + 1);
        splay(lnd);
        splay(rnd, lnd);
        son[rnd][0] = 0;
        update(rnd), update(lnd);
    }
};
SplayTree Tr;
int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    cin>>n>>m;
    for(int i = 2; i <= n + 1; i++)scanf("%d", a + i);
    a[1] = 0, a[n + 2] = 0;
    n += 2;
    Tr.init();
    
    for(int i = 1; i <= m; i++){
        string opt;
        int pos;
        cin>>opt;
        scanf("%d",&pos);
        if(opt[0] == D)Tr.erase(pos + 1);
        else printf("%d\n",Tr.query(pos + 1));
    }
    
}

18寒假第五測