刷题总结2/8

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题总结2/8相关的知识,希望对你有一定的参考价值。

本篇小重点:异或树https://www.luogu.com.cn/problem/P2846
用异或的0和1来模拟开关操作。一个区间只有亮灯和灭灯,所以异或之后区间亮灯的数量就是异或前区间灭灯的数量。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int a[maxn],n,m;
struct node

    int val,lazy;   //val记录一个区间内亮灯的数量,lazy与1异或来模拟明暗灯
sg[maxn<<2];
void pushup(int rt)

    sg[rt].val=sg[rt<<1].val+sg[rt<<1|1].val;

void pushdown(int rt,int ln,int rn)

    if(sg[rt].lazy)
    
        sg[rt<<1].lazy^=1;
        sg[rt<<1|1].lazy^=1;
        sg[rt<<1].val=ln-sg[rt<<1].val;//异或之后区间亮灯的数量就是异或前区间灭灯的数量
        sg[rt<<1|1].val=rn-sg[rt<<1|1].val;
        sg[rt].lazy=0;
    

void update(int L,int R,int l,int r,int rt)

    if(L<=l&&r<=R)
    
        sg[rt].val=(r-l+1)-sg[rt].val;
        sg[rt].lazy^=1;
        return;
    
    int m=(l+r)>>1;
    pushdown(rt,m-l+1,r-m);
    if(L<=m) update(L,R,l,m,rt<<1);
    if(R>m)  update(L,R,m+1,r,rt<<1|1);
    pushup(rt);

int query(int L,int R,int l,int r,int rt)

    if(L<=l&&r<=R)
        return sg[rt].val;
    if(L>r||R<l)
        return 0;
    int m=(l+r)/2;
    pushdown(rt,m-l+1,r-m);
    return query(L,R,l,m,rt<<1)+query(L,R,m+1,r,rt<<1|1);

signed main()

    scanf("%lld%lld",&n,&m);
    while(m--)
    
       int g,x,y;scanf("%lld%lld%lld",&g,&x,&y);
       if(g==0)
       
           update(x,y,1,n,1);
       
       else if(g==1)
       
           cout<<query(x,y,1,n,1)<<endl;
       
    
    return 0;



1.线段树2 加法和乘法的混合修改

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int a[maxn],n,m,p;
struct node

    int val,lazy,lz;
sg[maxn<<2];
void pushup(int rt)

    sg[rt].val=(sg[rt<<1].val+sg[rt<<1|1].val)%p;

void build(int l,int r,int rt)

    if(l==r)
    
        sg[rt].val=a[l];return ;
    
    sg[rt].lazy=0;
    sg[rt].lz=1;
    int m=(l+r)/2;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);

void pushdown(int rt,int ln,int rn)

    if(sg[rt].lazy||sg[rt].lz!=1)
    
        sg[rt<<1].val=(sg[rt].lazy*ln+(sg[rt<<1].val*sg[rt].lz)%p)%p;
        sg[rt<<1|1].val=(sg[rt].lazy*rn+(sg[rt<<1|1].val*sg[rt].lz)%p)%p;

        sg[rt<<1].lazy=(sg[rt].lazy+(sg[rt<<1].lazy*sg[rt].lz)%p)%p;
        sg[rt<<1|1].lazy=(sg[rt].lazy+(sg[rt<<1|1].lazy*sg[rt].lz)%p)%p;

        sg[rt<<1].lz=(sg[rt].lz*sg[rt<<1].lz)%p;
        sg[rt<<1|1].lz=(sg[rt].lz*sg[rt<<1|1].lz)%p;

        sg[rt].lz=1;
        sg[rt].lazy=0;
    

void update(int L,int R,int C,int l,int r,int rt)

    if(L<=l&&r<=R)
    
        sg[rt].val=(sg[rt].val+C*(r-l+1))%p;
        sg[rt].lazy=(sg[rt].lazy+C)%p;
        return;
    
    if(R<l||L>r) return;
    int m=(l+r)>>1;
    pushdown(rt,m-l+1,r-m);
    if(L<=m) update(L,R,C,l,m,rt<<1);
    if(R>m)  update(L,R,C,m+1,r,rt<<1|1);
    pushup(rt);


void update1(int L,int R,int C,int l,int r,int rt)

    if(R<l||L>r) return;
    if(L<=l&&r<=R)
    
        sg[rt].val=(sg[rt].val*C)%p;
        sg[rt].lazy=(sg[rt].lazy*C)%p;
        sg[rt].lz=(sg[rt].lz*C)%p;
        return;
    
    int m=l+r>>1;
    pushdown(rt,m-l+1,r-m);
    if(L<=m) update1(L,R,C,l,m,rt<<1);
    if(R>m) update1(L,R,C,m+1,r,rt<<1|1);
    pushup(rt);

int query(int L,int R,int l,int r,int rt)

    if(L<=l&&r<=R)
        return sg[rt].val;
    if(L>r||R<l)
        return 0;
    int m=(l+r)/2;
    pushdown(rt,m-l+1,r-m);
    return (query(L,R,l,m,rt<<1)+query(L,R,m+1,r,rt<<1|1))%p;

signed main()

    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<=n;i++)
    
        scanf("%lld",&a[i]);
    
    build(1,n,1);
    while(m--)
    
        //memset()
        int g;scanf("%lld",&g);
        if(g==2)
        
            int x,y,k;scanf("%lld%lld%lld",&x,&y,&k);
            update(x,y,k,1,n,1);
        
        else if(g==1)
        
            int x,y,k;scanf("%lld%lld%lld",&x,&y,&k);
            update1(x,y,k,1,n,1);
        
        else if(g==3)
        
            int x,y;scanf("%lld%lld",&x,&y);
            cout<<query(x,y,1,n,1)<<endl;
        
    
    return 0;


2.线段出取出区间极大值

#include <bits/stdc++.h>

using namespace std;
const int maxn=2e5+5;
int n,m,a[maxn];
struct node

    int val;
st[maxn<<2];
void pushup(int rt)

    st[rt].val=max(st[rt<<1].val,st[rt<<1|1].val);

void build(int l,int r,int rt)

    if(l==r)
    
        st[rt].val=a[l];
        return;
    
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);

void update(int L,int R,int l,int r,int rt)

    if(l==r)
    
        if(st[rt].val<R)
            st[rt].val=R;
        return;
    
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,l,mid,rt<<1);
    else update(L,R,mid+1,r,rt<<1|1);
    pushup(rt);

int query(int L,int R,int l,int r,int rt)

    if(L<=l&&r<=R)
        return st[rt].val;
    if(L>r||R<l)
        return 0;
    int mid=(l+r)>>1,ans=0;
    if(L<=mid)
        ans=max(ans,query(L,R,l,mid,rt<<1));
    if(R>mid)
        ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
    return ans;

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,n,1);
    while(m--)
    
        char c;scanf("%s",&c);int x,y;
        if(c=='Q'<

以上是关于刷题总结2/8的主要内容,如果未能解决你的问题,请参考以下文章

memset赋初值的运用

verilog 怎么对 寄存器组 赋初值

刷题3:队列的最大值

java刷题--239滑动窗口最大值

[JavaScript 刷题] 数组 - 极大极小游戏,leetcode 2293

Python | 快速获取某一列数组中前 N 个最大值/最小值的索引 | 三种方法总结