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));
    }

}

原文地址:https://www.cnblogs.com/EdSheeran/p/8445365.html

时间: 2024-08-30 18:13:38

18寒假第五测的相关文章

18寒假第三测

第一题:找LCA,两点之间的距离=他们各自到起点的距离 - 2*LCA到起点的距离 #include<bits/stdc++.h> using namespace std; const int maxn = 100015, P = 20; int head[2 * maxn],to[2 * maxn],last[2 *maxn],co[2 * maxn],dep[maxn], idx, anc[maxn][P+1],dis[maxn]; void dfs(int u,int from){ //

18寒假第六测

第一题:乘法修改的线段树 一定不能将change,modify分类讨论定两个标记,会有顺序影响 lazy标记一定要long long,又忘了... 代码和上一次差不多 第二题:离散暴力,也可以扫描线 离散时要将格子映射成点,不然会出现以下情况: 算横着的小矩形宽就是2,算黄色面积宽还是2,因为没有2让3去减 如果映射成点,就像这样,,放图比较好理解,就像扫描线,一个叶子节点存的是一个左闭右开的区间 也可以离散+扫描线,但还没写出来 #include <bits/stdc++.h> using

18寒假第一测

猪猪的想法输入文件:thought.in输出文件:thought.out时间限制:1 second空间限制:128 MB题目描述狗蛋养了许多只可爱的猪猪,这些猪猪她萌都有一些奇怪的想法:比如说猪猪喜欢猪猪,猪猪之间的喜欢是一个很有趣的事情--喜欢是可以传递的,例如猪猪喜欢猪猪,猪猪喜欢猪猪,那么可以说猪猪喜欢猪猪.有意思的一点是,她萌不喜欢自恋的猪猪,一旦出现了自恋的猪猪,那么极有可能的是这个团体出现危险.现在给你只猪猪对单方面的关系,请问这个只猪猪组成的团体是否危险呢?是输出Yes ,否输出N

18寒假第二测

第一题:二维树状数组,bit[x][y]表示从(1,1)到(x,y)的和,二维的坐标从一维的推过来,正确性可以用一个递增和一个递减的序列单调性证明,至于构图就当黑箱吧 #include <cstdio> int n, m, q; struct Case1 { int bit[100010]; void modify( int p, int d ) { for( int i = p; i <= m; i += i & -i ) bit[i] += d; } int query( i

18寒假13测

题目名称 buy slide divide 输入 buy.in slide.in divide.in 输出 buy.out slide.out divide.out 每个测试点时限 1秒 1秒 1秒 内存限制 256MB 256MB 256MB 测试点数目 10 10 10 每个测试点分值 10 10 10 是否有部分分 无 无 无 题目类型 传统 传统 传统 buy description: 地主zxr想买一些长方形的土地,所有的土地可以分为若干组,每一组的土地的价格为这一组里的最长的长乘上最

18寒假12测

Day1 题目名称 party array treasure 输入 party.in array.in treasure.in 输出 party.out array.out treasure.out 每个测试点时限 1秒 1秒 1秒 内存限制 64MB 64MB 64MB 测试点数目 10 10 10 每个测试点分值 10 10 10 是否有部分分 无 无 无 题目类型 传统 传统 传统 party 题目描述: 在M公司里,每个人只有一个直属上司(除了boss).这个公司举办派对,每个人可以给派

NOI十连测 第五测 T1

1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 int f[257][257],n,type,V[257],g[257][257],ans,cnt; 7 char op[204]; 8 int read(){ 9 int t=0,f=1;char ch=getchar(); 10 while

寒假第五周 2.8 --- 2.14

寒假过了一半了诶 什么都没有干的感觉. 真的是新的一年了>_< 过去的2015,如果说学到了什么的话,大概是充分意识到 ----- 我是 sb 另外还有身体很重要,不要等到难受的时候才想起要是平时有多锻炼锻炼就好了 新的2016 好好学习,天天向上 就是这样 新的一年更加有趣 gooooooooooooooooooooooooooooooooo>_< 2.8

NOI十连测 第五测 T2

思路:考虑建立可持久化线段树,第一层维护的是i这个位置的next位置,第二层,维护的是接下来走这个字符会到哪个节点. 感觉很巧妙啊,不愧是Claris 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int v[18000005],l[18000005],r[18000005],sz; 7 i