P2184 贪婪大陆 线段树

  题意:

一共有两种操作

1. 给区间  L R  每个位置加上一种 标记

2.询问区间 L R 一共有多少种标记

之前做到过一种简易版的 (区间染色count color)(标记只有三十种 ) 所以可以用位运算模拟

还有一个差别就是那种会覆盖掉   这种是无限累加

显然表示某个区间的状态是很难实现的

对每个操作1  可以插入两个点表示头和尾

答案为   1-R 的头标记数  减去 1-(L-1)的尾标记数!!!

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
const int N=1e5+5;

int head[N<<2],tail[N<<2];
int sumhead[N<<2],sumtail[N<<2];

void up(int pos)
{
    head[pos]=head[pos<<1]+head[pos<<1|1];
    tail[pos]=tail[pos<<1]+tail[pos<<1|1];
}
void update(int x,int flag,int l,int r,int pos)
{
    if(l==r)
    {
        if(flag==1)head[pos]++;
        else  tail[pos]++;
        return ;
    }
    int m=(l+r)>>1;
    if(x<=m)update(x,flag,lson);
    else update(x,flag,rson);
    up(pos);
}
int query(int L,int R,int flag,int l,int r,int pos)
{
    if(L<=l&&r<=R)
    {
        if(flag==1)return head[pos];
        else if(flag==2)return tail[pos];
    }
    int ans=0;
    int m=(l+r)>>1;
    if(L<=m)ans+=query(L,R,flag,lson);
    if(R>m)ans+=query(L,R,flag,rson);
    up(pos);
    return ans;
}
int n,m,a,b,c;
int main()
{
    RII(n,m);
    while(m--)
    {
        RIII(a,b,c);
        if(a==1){update(b,1,1,n,1);update(c,2,1,n,1);}
        else  cout<<query(1,c,1,1,n,1)-query(1,b-1,2,1,n,1)<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/10915195.html