线段树

线段树:

注意 : 4倍 空间 4倍空间

   ╮(╯▽╰)╭,一直有点半懂不懂 , 这些应该可以了

树的建立: 注意 l==r 时要return!!!

void build(int l,int r,int i)
{
    p[i].l=l;
    p[i].r=r;
    if(p[i].l==p[i].r)
    {
        p[i].hz=p[i].mz=p[i].qz=1;
        return ;        ///////////////// 关键 
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    up(i); // gen xin
}
View Code

懒标记:  超级重要,一定要对每一道提具体分析,懒标记的转移一定要正确。

void down(int i)
{
    if(p[i].lazy==0) return; 
     p[i<<1].lazy=p[i<<1|1].lazy=p[i].lazy; // 标记跟新 
    if(标记满足什么)
    {
       跟新什么    
    }
    p[i].lazy=0; // 注意!!!!!!!!! 
}
View Code

上传:

void up(int i)
{
    p[i].状态=p[i<<1].状态+p[i<<1|1].状态; 
}
View Code

树的修改:

void  xiu(int l,int r,int i)
{
    
    if(l>p[i].r||r<p[i].l) return ;
    if(l<=p[i].l&&p[i].r<=r)
    {
        lazy[i]^=1;         /// LAZY 是帮忙记录儿子的信息,不是自己的 
        p[i].sum=(p[i].r-p[i].l+1)-p[i].sum;  // 更新自己的信息 
        return ; //// 下传递很重要 
    }
    down(i);        
    xiu(l,r,i<<1);
    xiu(l,r,i<<1|1);
    up(i);             // 上传递很重要 
}
View Code

树的查询(有时候不一样):

long long  cha(int l,int r,int i,int k)
{
    if(l>p[i].r||r<p[i].l) return 相反的;
    if(l<=p[i].l&&p[i].r<=r)
     {
         if(k满足什么状态)
        return p[i].状态;  // ruturn 
     }
     return  2个状态 cha(l,r,i*2,k),chaa(l,r,i*2+1,k)
}
View Code

 特别:

int cha(int i,int x)
{
    down(i);
    if(p[i].r-p[i].l+1==x&&p[i].mz==x) return p[i].l;
    if(p[i<<1].mz>=x) return cha(i<<1,x);
    if(p[i<<1].hz+p[i<<1|1].qz>=x) return  p[i<<1].r-p[i<<1].hz+1;
    if(p[i<<1|1].mz>=x) return cha(i<<1|1,x);
    return 0;
}
View Code

例题:

1824: 【高级数据结构】Hotel
时间限制: 1 Sec  内存限制: 64 MB
提交: 18  解决: 7
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
    奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的
湖面。
    贝茜一行,以及其他慕名而来的旅游者,都是一批批地来到旅馆的服务台,希望能订到D_i (1 <= D_i <= N)间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为r..r+D_i-1的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。
旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字X_i、D_i描述,表示编号为X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1)房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。
    而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理M (1 <= M < 50,000)个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。
输入
* 第1行: 2个用空格隔开的整数:N、M
* 第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字: 1、D_i描述,数字间用空格隔开;
如果它是一个退房请求,用3个以空格隔开的数字: 2、X_i、D_i描述
输出
* 第1..??行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足,输出满足条件的最小的r;如果请求无法被满足,输出0
样例输入 Copy
10 6
1 3
1 3
1 3
1 3
2 5 5
1 6
样例输出    Copy
1
4
7
0
5
View Code

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 50005;
const int M = 50005;
#define ri register int
struct settree{
    int l,r,qz,hz,mz,lazy;
}p[N*4+5];
void up(int i)
{
    p[i].mz=max(max(p[i<<1].mz,p[i<<1|1].mz),p[i<<1].hz+p[i<<1|1].qz);
    p[i].qz=p[i<<1].qz;
     
     if(p[i].qz==p[i<<1].r-p[i<<1].l+1)
     p[i].qz+=p[i<<1|1].qz;
     p[i].hz=p[i<<1|1].hz;
     if(p[i].hz==p[i<<1|1].r-p[i<<1|1].l+1)
     p[i].hz+=p[i<<1].hz;
}
void build(int l,int r,int i)
{
    p[i].l=l;
    p[i].r=r;
    if(p[i].l==p[i].r)
    {
        p[i].hz=p[i].mz=p[i].qz=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    //p[i].hz=p[i].mz=p[i].qz=(r-l+1); //
    up(i);
}
void down(int i)
{
    if(p[i].lazy==0) return; 
    if(p[i].lazy==1)
    {
       p[i<<1].lazy=p[i<<1|1].lazy=1;
       p[i<<1].mz=p[i<<1].qz=p[i<<1].hz=p[i<<1].r-p[i<<1].l+1;
       p[i<<1|1].mz=p[i<<1|1].qz=p[i<<1|1].hz=p[i<<1|1].r-p[i<<1|1].l+1;      
    }
    else
    {
         p[i<<1].lazy=p[i<<1|1].lazy=2;
         p[i<<1].mz=p[i<<1].qz=p[i<<1].hz=0;
         p[i<<1|1].mz=p[i<<1|1].qz=p[i<<1|1].hz=0;    
    }
    p[i].lazy=0;
}
int cha(int i,int x)
{
    down(i);
    if(p[i].r-p[i].l+1==x&&p[i].mz==x) return p[i].l;
    if(p[i<<1].mz>=x) return cha(i<<1,x);
    if(p[i<<1].hz+p[i<<1|1].qz>=x) return  p[i<<1].r-p[i<<1].hz+1;
    if(p[i<<1|1].mz>=x) return cha(i<<1|1,x);
    return 0;
}
void xiu(int l,int r,int i,int k)
{
    if(r<p[i].l||l>p[i].r) return;
    if(l<=p[i].l&&p[i].r<=r)
    {
        if(k==1)
        {
            p[i].mz=p[i].qz=p[i].hz=p[i].r-p[i].l+1;
            p[i].lazy=1;
        }
        else
        {
            p[i].mz=p[i].qz=p[i].hz=0;
            p[i].lazy=2;
        }
        return ;
    }
    down(i);
    xiu(l,r,i<<1,k);
    xiu(l,r,i<<1|1,k);
    up(i);
}
int n,m;
int main(){
    scanf("%d%d",&n,&m);
    build(1,n,1);
    for(ri i=1;i<=m;i++)
    {
        int opt;
        scanf("%d",&opt);
        if(opt==1)
        {
            int x;
            scanf("%d",&x);
            int ans=cha(1,x);
            printf("%d\n",ans);
            if(ans) xiu(ans,ans+x-1,1,2);
        }
        else
        {
            int L,R;
            scanf("%d%d",&L,&R);//
            xiu(L,L+R-1,1,1);
        }
    }
}
View Code

 例题:懒标记的重要:

Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每一头被连续的编号为1..N, 站在一个彩色的灯下面. 
刚到傍晚的时候, 所有的灯都是关闭的. 奶牛们通过N个按钮来控制灯的开关; 按第i个按钮可以改变第i个灯的状态. 
奶牛们执行M (1 <= M <= 100,000)条指令, 每个指令都是两个整数中的一个(0 <= 指令号 <= 1). 
第1种指令(用0表示)包含两个数字S_i和E_i (1 <= S_i <= E_i <= N), 它们表示起始开关和终止开关. 奶牛们只需要把从S_i到E_i之间的按钮都按一次, 就可以完成这个指令. 
第2种指令(用1表示)同样包含两个数字S_i和E_i (1 <= S_i <= E_i <= N), 不过这种指令是询问从S_i到E_i之间的灯有多少是亮着的. 
帮助FJ确保他的奶牛们可以得到正确的答案. 
输入
第 1 行: 用空格隔开的2个整数N和M
第 2..M+1 行: 每行表示一个操作, 有3个用空格分开的整数: 指令号, S_i 和 E_i 
输出
第 1..询问的次数 行: 对于每一次询问, 输出询问的结果. 
样例输入 Copy
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4
样例输出    Copy
1
2
View Code

 代码(错误代码):

#include <bits/stdc++.h>
using namespace std;
const int N = 100400;
const int M = 100000;
#define ri register int 
struct settree{
    int l,r,sum,lazy,num;
}p[N*4+5];
int val[N];
int n;
void build(int l,int r,int i)
{
    p[i].l=l;
    p[i].r=r;
    if(l==r)
    {
    return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
}
void down(int i)
{
    if(p[i].lazy==0) return;
    p[i<<1].lazy+=p[i].lazy;
    p[i<<1|1].lazy+=p[i].lazy; ///////////
    p[i<<1].num+=p[i].lazy;
    p[i<<1|1].num+=p[i].lazy;
    if(p[i<<1].num%2==1)
     p[i<<1].sum=p[i<<1].r-p[i<<1].l+1;
     else
     p[i<<1].sum=0;
     if(p[i<<1|1].num%2==1)
     p[i<<1|1].sum=p[i<<1|1].r-p[i<<1|1].l+1;
     else
     p[i<<1|1].sum=0;
    p[i].lazy=0;
}
void build2(int i)
{
    if(p[i].l==p[i].r)
    {
     val[p[i].l]=p[i].sum;
     return ;
    }
    down(i);
    build2(i<<1);
    build2(i<<1|1);
}
void xiu(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return;
    if(l<=p[i].l&&p[i].r<=r)
    {
        p[i].lazy++;
        p[i].num++;
        if(p[i].num%2==1)
         p[i].sum=(p[i].r-p[i].l+1);
         else
         p[i].sum=0;
        return ;
    }
    down(i);
    xiu(l,r,i<<1);
    xiu(l,r,i<<1|1);
    p[i].sum=p[i<<1].sum+p[i<<1|1].sum;
}
int ans;
int cha(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return 0;
    if(l<=p[i].l&&p[i].r<=r)
    {   
        return p[i].sum;
    }
    down(i);
    return cha(l,r,i<<1)+cha(l,r,i<<1|1);
}
int m;
int main(){
   scanf("%d",&n);
    build(1,n,1);
    scanf("%d",&m);
    for(ri i=1;i<=m;i++)
    {
        int L,R,X;
        int opt;
        scanf("%d",&opt);
        if(opt==0)
        {
        scanf("%d%d",&L,&R);
        xiu(L,R,1);
        }
        else
        {
            scanf("%d%d",&L,&R);
            printf("%d\n",cha(L,R,1));
        }
    }
 
}
View Code

正确代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 100400;
const int M = 100000;
#define ri register int 
struct settree{
    int l,r,sum,lazy,num;
}p[N*4+5];
int val[N];
int n;
void build(int l,int r,int i)
{
    p[i].l=l;
    p[i].r=r;
    if(l==r)
    {
    return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
}
void down(int i)
{
    if(p[i].lazy==0) return;
    p[i<<1].lazy^=1;
    p[i<<1|1].lazy^=1; ///////////
    p[i<<1].sum=p[i<<1].r-p[i<<1].l+1-p[i<<1].sum;  
    p[i<<1|1].sum=p[i<<1|1].r-p[i<<1|1].l+1-p[i<<1|1].sum;
    p[i].lazy=0;
}
void build2(int i)
{
    if(p[i].l==p[i].r)
    {
    printf("%d",p[i].num%2);
     return ;
    }
    down(i);
    build2(i<<1);
    build2(i<<1|1);
}
void xiu(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return;
    if(l<=p[i].l&&p[i].r<=r)
    {
        p[i].lazy^=1;
        p[i].sum=(p[i].r-p[i].l+1)-p[i].sum;
        return ;
    }
    down(i);
    xiu(l,r,i<<1);
    xiu(l,r,i<<1|1);
    p[i].sum=p[i<<1].sum+p[i<<1|1].sum;
}
int ans;
int cha(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return 0;
    if(l<=p[i].l&&p[i].r<=r)
    {   
        return p[i].sum;
    }
    down(i);
    return cha(l,r,i<<1)+cha(l,r,i<<1|1);
}
int m;
int main(){
   scanf("%d",&n);
    build(1,n,1);
    scanf("%d",&m);
    for(ri i=1;i<=m;i++)
    {
        int L,R,X;
        int opt;
        scanf("%d",&opt);
        if(opt==0)
        {
        scanf("%d%d",&L,&R);
        xiu(L,R,1);
        }
        else
        {
            scanf("%d%d",&L,&R);
            printf("%d\n",cha(L,R,1));
        }
    }

 
}
View Code

 啊

  

原文地址:https://www.cnblogs.com/Lamboofhome/p/11388224.html