ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线段树(题集

2020-07-05 17:01:38  阅读:202  来源: 互联网

标签:const int 线段 题集 long tag return include


 

 

扶苏学长给我们讲了线段树、树状数组、主席树等数据结构

并发布了练习题单……

 

题目:

 

A:

只需将maketag函数更改为异或和即可

然后tag的更新方式更改

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const long long  k=5e5+5;

long long  a[k];

struct Segment{
    long long  l,r;
    long long  sum;
    long long  tag;
    Segment *lef,*rig;
    
    Segment(const long long  L,const long long  R )
    {
        l=L;r=R;
        tag=0;
        if(l != r)
        {
            int mid=l+r>>1;
            lef=new Segment(l,mid);
            rig=new Segment(mid+1,r);
            sum=lef->sum +rig->sum ;
            tag=0;
        }
        else{
            lef=rig=NULL;
            sum=a[l];
        }
    }
    
    inline void maketag(){
        sum=(r-l+1)-sum;
        tag^=1;
    }
    
    void spread()
    {
//        if(lef == NULL) lef=new Segment(l,mid);
//        if(rig == NULL) rig =new Segment(mid+1,r);
        if(tag==0) return;
        else {
            lef->maketag();
            rig->maketag();
            tag=0;
        }
    }    

    inline bool Out(const long long  L,const long long  R) { return (R<l || r<L ) ;}

    void change(long long  L,long long  R)
    {
        if(L<=l && r<=R){
            maketag();
        }
        else {
            if(Out(L,R)) return ;
            else{
            spread();
            lef->change(L,R);
            rig->change(L,R);
            sum=lef->sum+rig->sum;
            } 
            
        }
    }
    
    
    long long  ask(long long  L,long long  R)
    {
        if(L<=l && r<=R) return sum;
        else {
            if(Out(L,R)) return 0;
            else{
            spread();
            return lef->ask(L,R)+rig->ask(L,R);
            
            } 
            
        }
    }
    
};

Segment *root;

int  main(void)
{
    long long  n,m,q;
    string str;
    
    ios_base::sync_with_stdio(false);
    cout.tie(NULL);
    cin.tie(NULL);
    
    cin>>n>>m;
    
    cin>>str;
    
    for(long long  i=1;i<=n;i++)
    {
        int q=str[i-1]-'0';
        a[i]=q;
    }
    
    root=new Segment(1,n);
    
    for(long long  i=1;i<=m;i++)
    {
        long long  x,y,z,g;
        cin>>x>>y>>z;
        
        if(x==0){
            root->change(y,z);
        }
        else {
            cout<<root->ask(y,z)<<'\n';
        }
    }
}

 

B、D:

模板不多说

 

C:
该题没有修改,只有询问,所以只维护一个最小值即可

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const long long  k=5e5+5;

long long  a[k];

struct Segment{
    long long  l,r;
    long long  sum;
    long long  tag;
    Segment *lef,*rig;
    
    Segment(const long long  L,const long long  R )
    {
        l=L;r=R;
        tag=0;
        if(l != r)
        {
            int mid=l+r>>1;
            lef=new Segment(l,mid);
            rig=new Segment(mid+1,r);
            sum=min(lef->sum,rig->sum);
            tag=0;
        }
        else{
            lef=rig=NULL;
            sum=a[l];
        }
    }
    inline bool Out(const long long  L,const long long  R) { return (R<l || r<L ) ;}


    long long  ask(long long  L,long long  R)
    {
        if(L<=l && r<=R) return sum;
        else {
            if(Out(L,R)) return 1<<30;
            else{
            return  min(lef->ask(L,R),rig->ask(L,R));
            
            } 
            
        }
    }
    
};

Segment *root;

int  main(void)
{
    long long  n,m,q;
    
    ios_base::sync_with_stdio(false);
    cout.tie(NULL);
    cin.tie(NULL);
    
    cin>>n>>m;
    
    for(int i=1;i<=n;i++)
    cin>>a[i];
    
    root=new Segment(1,n);
    
    for(long long  i=1;i<=m;i++)
    {
        long long  x,y,z;
        cin>>x>>y;
    
        cout<<root->ask(x,y)<<" ";
    }
}

 

 

F:

维护一个区间和与一个区间平方和

再对方差公式进行推导

即可

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 using namespace std;
  7 const int maxn=100005;
  8 double a[maxn];
  9 int n,q;
 10 struct Node{
 11     double v1,v2,tag;
 12     int l,r;
 13     Node *ls,*rs;
 14     Node(const int L,const int R){
 15         l=L,r=R;
 16         if(l==r){
 17             tag=0;
 18             v1=a[l];
 19             v2=a[l]*a[l];//v2表示序列平方和,初始化为平方 
 20             rs=ls=NULL;
 21         }
 22         else{
 23             tag=0;
 24             int M=(L+R)>>1;
 25             ls=new Node(L,M);
 26             rs=new Node(M+1,R);
 27             pushup();
 28         }
 29     }
 30     inline void pushup(){
 31         v1=ls->v1+rs->v1;
 32         v2=ls->v2+rs->v2;
 33     }
 34     inline void pushdown(){
 35         if(tag==0) return;
 36         else{
 37             ls->maketag(tag);
 38             rs->maketag(tag);
 39             tag=0;
 40         }
 41     }
 42     inline void maketag(double w){
 43         v2=v2+(r-l+1)*w*w+2*w*v1;//根据公式计算,注意一定要先更新v2再更新v1,因为更新v2要用到原序列的和 
 44         v1+=(r-l+1)*w;
 45         tag+=w;
 46     }
 47     inline bool InRange(const int L,const int R){
 48         return (l>=L)&&(r<=R);
 49     }
 50     inline bool OutofRange(const int L,const int R){
 51         return (l>R)||(r<L);
 52     }
 53     inline void upd(const int L,const int R,double w){
 54         if(InRange(L,R)){
 55             maketag(w);
 56         }else if(!OutofRange(L,R)){
 57             pushdown();
 58             ls->upd(L,R,w);
 59             rs->upd(L,R,w);
 60             pushup();
 61         }
 62     }
 63     double qry(const int L,const int R){
 64         if(InRange(L,R)){
 65             return v1;
 66         }
 67         if(OutofRange(L,R)){
 68             return 0;
 69         }
 70         else{
 71             pushdown();
 72             return ls->qry(L,R)+rs->qry(L,R);
 73         }
 74     }
 75     double qry1(const int L,const int R){
 76         if(InRange(L,R)){
 77             return v2;
 78         }
 79         if(OutofRange(L,R)){
 80             return 0;
 81         }
 82         else{
 83             pushdown();
 84             return ls->qry1(L,R)+rs->qry1(L,R);
 85         }
 86     }
 87 };
 88 int main()
 89 {
 90     scanf("%d%d",&n,&q);
 91     for(int i=1;i<=n;i++){
 92         scanf("%lf",a+i);
 93     }
 94     Node *rot=new Node(1,n);
 95     for(int i=1;i<=q;i++){
 96         int o,x,y;
 97         double z;
 98         scanf("%lld%d%d",&o,&x,&y);
 99         if(x>y){
100             swap(x,y);
101         }
102         if(o==1){
103             scanf("%lf",&z);
104             rot->upd(x,y,z);
105         }
106         if(o==2){
107             printf("%.4lf\n",(rot->qry(x,y))/(y-x+1));
108         }
109         if(o==3){
110             double s1=rot->qry1(x,y);//平方和 
111             double s2=(rot->qry(x,y))/(y-x+1);//平均数
112             double s3=rot->qry(x,y);//和
113             printf("%.4lf\n",((s1-2*s2*s3+(y-x+1)*s2*s2)/(y-x+1)));//根据公式计算 
114         }
115     }
116     return 0;
117 }

 

G:

多次试验表明,我煎不出来。。。

等扶苏学长来讲吧

 

H:

本题需要使用状压优化与位运算

初始时将所有颜色用二进制数表示

每次上色将对应的数值更新

下传标记为直接覆盖

上传信息时,将两个数进行或运算

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<ctime>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<algorithm>
  8  
  9 using namespace std;
 10  
 11 int l, t, o, lf, rt, color;
 12 char op;
 13  
 14 struct Node{
 15     int l, r;
 16     long long tag, v;
 17     Node *ls, *rs;
 18      
 19     inline bool InRange(const int L, const int R){
 20         return (L <= l) && (r <= R);
 21     }
 22     inline bool OutofRange(const int L, const int R){
 23         return (L > r) || (l > R);
 24     } 
 25     inline void maketag(const long long x){
 26         tag = x;//????????????????? 
 27         v = x;//?????? 
 28     }
 29     inline void pushdown(){
 30         if(tag == 0)    return;//?????????????У????????′????????? 
 31         ls->maketag(tag);
 32         rs->maketag(tag);
 33         tag = 0;
 34     }
 35     inline void pushup(){
 36         /*if(ls != NULL){
 37             v |= ls->v;
 38         }
 39         if(rs != NULL){
 40             v |= rs->v;
 41         }*/
 42         v = (ls->v) | (rs->v);
 43     }
 44     Node (const int L, const int R){
 45         l = L;
 46         r = R; 
 47         tag = 0;
 48         if(L == R){
 49             tag = 0;
 50             v = 1 << 1;
 51             ls = NULL;
 52             rs = NULL;
 53         }
 54         else {
 55             int M = (l + r) >> 1;
 56             ls = new Node(l, M);
 57             rs = new Node(M + 1, R);
 58             pushup();
 59         }
 60     }
 61     inline void upd(const int L, const int R, const long long x){
 62         if(InRange(L, R)){
 63             maketag(x);
 64         }
 65         else if(!OutofRange(L, R)){
 66             pushdown();
 67             ls->upd(L, R, x);
 68             rs->upd(L, R, x);
 69             pushup(); 
 70         }
 71     }
 72     inline long long query(const int L, const int R){
 73         if(InRange(L, R)){
 74             return v;
 75         }
 76         else if(!OutofRange(L, R)){
 77             pushdown();
 78             return ls->query(L, R) | rs->query(L, R);
 79         }
 80         else return 0;
 81     }
 82 };
 83  
 84 inline int bit(const long long n){
 85     int res = 0, n0 = n;
 86     while(n0){
 87         res += (n0 & 1);
 88         n0 >>= 1;
 89     }
 90     return res;
 91 }
 92  
 93 int main(){
 94     scanf("%d%d%d",&l,&t,&o);
 95     Node *rot = new Node(1,l);
 96      
 97     for(int i=1;i<=o;i++){
 98         cin >> op;
 99         if(op == 'C'){
100             scanf("%d%d%d",&lf,&rt,&color);
101             if(lf > rt)  swap(lf, rt);
102             rot->upd(lf,rt,(long long)1<<color);
103         }
104         else{
105             scanf("%d%d",&lf,&rt);
106             if(lf > rt)  swap(lf, rt);
107             printf("%d\n",bit(rot->query(lf,rt)));
108         } 
109     }
110      
111     return 0;
112 }

 

I、J:

这两个题mod做

 

E将会在树状数组时进行讲解

另:《棠梨煎雪》可以通过树状数组拿到可观的部分分

 

-end-

 

标签:const,int,线段,题集,long,tag,return,include
来源: https://www.cnblogs.com/-Iris-/p/13246751.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有