校门外的树线段树做法

来源:互联网 发布:二手雷克萨斯es240知乎 编辑:程序博客网 时间:2024/04/29 04:55
#include<bits/stdc++.h>//包括所有常用头文件,有些版本不兼容using namespace std;struct node {      int left;      int right;      int count; }a[100010];  int ans;  void build(int l, int r, int k) {      a[k].left=l;      a[k].right=r;     a[k].count=1;  //设初值     if(l==r)          return;      build(l,(l+r)/2,k*2);      build((l+r)/2+1,r,k*2+1);  //继续创建}  void query(int l, int r, int k) {      if(a[k].left==l&&a[k].right==r)  {         a[k].count=0;         return ;      }//重合    if(a[k].count==0)return;//已经没有树了,就不要搜了    if(a[k].left == a[k].right)  //左右界重合        return ;    a[k].count=2;//有0有1标记    if(r<=(a[k].left+a[k].right)/2)          query(l,r,k*2);      else if(l>(a[k].left + a[k].right)/2)          query(l,r,k*2+1);      else {          query(l, (a[k].left + a[k].right)/2, k*2);          query((a[k].left + a[k].right)/2+1, r, k*2+1);      }//继续搜} void pluss(int k) {    if(a[k].count==1){        ans+=a[k].right-a[k].left+1;        return;    }//只要为一,代表子树都为一,累加    if(a[k].count==2){        pluss(k*2);        pluss(k*2+1);    }//只要是二,就代表还要搜} int main(){    int i,n,m,k,x,y,z;    scanf("%d",&n);    build(1,n+1,1);//建立一个线段树    scanf("%d",&m);    for(i=1;i<=m;i++){        scanf("%d%d",&x,&y);        query(x+1,y+1,1);//标记    }    pluss(1);//累加    cout<<ans;    return 0;}

ps:这题就完美转化为校门外的线段树了,呵呵呵
再ps:不要担心爆系统栈,栈只会用log2(n)

1 0