【Tyvj】1473校门外的树3 线段树/树状数组 <区间修改+单点访问>

描述

 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
K=1,读入l,r表示在l~r之间种上的一种树
K=2,读入l,r表示询问l~r之间能见到多少种树
(l,r>0)

输入格式

第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作

输出格式

对于每个k=2输出一个答案

测试样例1

输入

5 4 
1 1 3 
2 2 5 
1 2 4 
2 3 5

输出


2

备注

范围:20%的数据保证,n,m<=100
      60%的数据保证,n <=1000,m<=50000
      100%的数据保证,n,m<=50000
注意:树是可以重叠的,比如1号位置上可以种多种树

题解

    用两个线段树维护每个节点左右端点个数,端点数即是该点上覆盖的线段;

代码

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <ctime>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <set>
  8 #include <vector>
  9 #include <queue>
 10 #include <typeinfo>
 11 #include <map>
 12 #include <stack>
 13 typedef long long ll;
 14 #define inf 0x7fffffff
 15 using namespace std;
 16 inline ll read()
 17 {
 18     ll x=0,f=1;
 19     char ch=getchar();
 20     while(ch<'0'||ch>'9')
 21     {
 22         if(ch=='-')f=-1;
 23         ch=getchar();
 24     }
 25     while(ch>='0'&&ch<='9')
 26     {
 27         x=x*10+ch-'0';
 28         ch=getchar();
 29     }
 30     return x*f;
 31 }
 32 //**************************************************************************************
 33 int n,m;
 34 struct ss
 35 {
 36     int l,r;
 37     int left,right;
 38 } tr[200001];
 39 void build(int k,int s,int t)
 40 {
 41     tr[k].left=s;
 42     tr[k].right=t;
 43     if(s==t)return;
 44     int mid=(s+t)>>1;
 45     build(k<<1,s,mid);
 46     build(k<<1|1,mid+1,t);
 47 }
 48 void insertl(int k,int x,int y)
 49 {
 50     int l=tr[k].left,r=tr[k].right;
 51     if(l==x&&y==r)
 52     {
 53         tr[k].l++;
 54         return;
 55     }
 56     int mid=(l+r)>>1;
 57     if(y<=mid)insertl(k<<1,x,y);
 58     else if(x>mid)insertl(k<<1|1,x,y);
 59     else
 60     {
 61         insertl(k<<1,x,mid);
 62         insertl(k<<1|1,mid+1,y);
 63     }
 64 }
 65 void insertr(int k,int x,int y)
 66 {
 67     int l=tr[k].left,r=tr[k].right;
 68     if(l==x&&y==r)
 69     {
 70         tr[k].r++;
 71         return;
 72     }
 73     int mid=(l+r)>>1;
 74     if(y<=mid)insertr(k<<1,x,y);
 75     else if(x>mid)insertr(k<<1|1,x,y);
 76     else
 77     {
 78         insertr(k<<1,x,mid);
 79         insertr(k<<1|1,mid+1,y);
 80     }
 81 }
 82 int askl(int k,int x)
 83 {
 84     int l=tr[k].left,r=tr[k].right;
 85     if(l==r)return tr[k].l;
 86     int mid=(l+r)>>1;
 87     if(x<=mid)return tr[k].l+askl(k<<1,x);
 88     else return tr[k].l+askl(k<<1|1,x);
 89 }
 90 int askr(int k,int x)
 91 {
 92     int l=tr[k].left,r=tr[k].right;
 93     if(l==r)return tr[k].r;
 94     int mid=(l+r)>>1;
 95     if(x<=mid)return tr[k].r+askr(k<<1,x);
 96     else return tr[k].r+askr(k<<1|1,x);
 97 }
 98 int main()
 99 {
100     int total=0,ans;
101     scanf("%d%d",&n,&m);
102     build(1,0,n);//l最小为1,所以是0到n
103     for(int i=1; i<=m; i++)
104     {
105         int t,a,b;
106         scanf("%d%d%d",&t,&a,&b);
107         if(t==1)
108         {
109             insertl(1,0,a-1);//考虑到a==1
110             insertr(1,b+1,n);
111             total++;
112         }
113         else
114         {
115             ans=askr(1,a)+askl(1,b);
116             printf("%d\n",total-ans);
117         }
118     }
119     return 0;
120 }

 

posted @ 2015-07-29 01:21  meekyan  阅读(327)  评论(0编辑  收藏  举报