P2184 贪婪大陆

面对蚂蚁们的疯狂进攻,小 FF 的 Tower defence 宣告失败……人类被蚂蚁们逼到了 Greed Island 上的一个海湾。现在,小 FF 的后方是一望无际的大海,前方是变异了的超级蚂蚁。小 FF 还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造 SCV 布置地雷以阻挡蚂蚁们的进攻。
题目描述
小 FF 最后一道防线是一条长度为 n 的战壕,小 FF 拥有无数多种地雷,而 SCV 每次可以在 [L,R] 区间埋放同一种不同于之前已经埋放的地雷。由于情况已经十万火急,小 FF 在某些时候可能会询问你在 [L′,R′] 区间内有多少种不同的地雷,他希望你能尽快的给予答复。
输入格式
第一行为两个整数 n 和 m,n 表示防线长度,m 表示 SCV 布雷次数及小 FF 询问的次数总和。
接下来有 m 行,每行三个整数 q,l,r:
若 q=1,则表示 SCV 在[l,r] 这段区间布上一种地雷;
若 q=2,则表示小 FF 询问当前[l,r] 区间总共有多少种地雷。
输出格式
对于小 FF 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。
输入输出样例
5 4
1 1 3
2 2 5
1 2 4
2 3 5
输出
1
2

题目分析
将区间修改改为单点修改,即只记录起点和终点。如需要在【1,3】中种下地雷,则记录起点1的地雷数++,终点3的地雷数++。求解【l,r】的地雷数问题就转化为求解【1,r】的所有起点地雷-以【1,l-1】为终点的地雷数。
用线段树来维护。

点击查看代码
#include<iostream>
#include<vector>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200020
#define ls u<<1
#define rs u<<1|1
int d;
struct tree
{
   int l,r;
   ll sum1,sum2;//sum1维护起点地雷,sum2维护终点地雷


}tr[N*4];
void pushup(int u)
{
    tr[u].sum1=tr[ls].sum1+tr[rs].sum1;
    tr[u].sum2=tr[ls].sum2+tr[rs].sum2;
    return ;


}
void build(int u,int l,int r)
{
    tr[u]={l,r,0,0};
    if(l==r)
   {
       return ;
   }
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
}
void change(int x,int u,int f)
{
     if(tr[u].l==x&&tr[u].r==x)
        {
            if(f)
            tr[u].sum1+=1;
            else
            tr[u].sum2+=1;
            return ;
        }
     int m=tr[u].l+tr[u].r>>1;
     if(x<=m)
     change(x,ls,f);
     else
     change(x,rs,f);
     pushup(u);

}
int query1(int u,int l,int r)
{
    if(l<=tr[u].l&&tr[u].r<=r)
        return tr[u].sum1;
    int m=tr[u].l+tr[u].r>>1;
    int ans=0;
    if(l<=m) ans+=query1(ls,l,r);
    if(r>m) ans+=query1(rs,l,r);
    return ans;
}
int query2(int u,int l,int r)
{
    if(l<=tr[u].l&&tr[u].r<=r)
        return tr[u].sum2;
    int m=tr[u].l+tr[u].r>>1;
    int ans=0;
    if(l<=m) ans+=query2(ls,l,r);
    if(r>m) ans+=query2(rs,l,r);
    return ans;
}
int main()
{
     cin.tie(NULL);
     cout.tie(nullptr);
     ios_base::sync_with_stdio(false);
     int q,m,n;
     int c,x,y;
     int t;
     cin>>n>>m;
     build(1,1,n);
     for(int i=1;i<=m;i++)
     {
       cin>>c>>x>>y;
       if(c==1)
       {
           change(x,1,1);
           change(y,1,0);

       }
       else {
        cout<<query1(1,1,y)-query2(1,1,x-1)<<'\n';
       }



     }


     return 0;
}

**请注意:思路来自哔哩哔哩的董晓算法**
posted @ 2024-01-23 23:20  WandW  阅读(18)  评论(0)    收藏  举报