18寒假第五测

Posted Ed_Sheeran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18寒假第五测相关的知识,希望对你有一定的参考价值。

第一题 线段树

树状数组存差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寒假第五测的主要内容,如果未能解决你的问题,请参考以下文章

NOI十连测 第五测 T2

暑假第五测

9.26ZR七连测第五测总结

2018年全国多校算法寒假训练营练习比赛(第五场)题解

寒假第五周 2.8 --- 2.14

纪中五测