【洛谷 P2184】贪婪大陆

好几天没更新了

这几天还是在做线段树的题目
后面,可能做点DP?
这块不是很熟的样子

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 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。

输入输出样例 #1

输入 #1

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

输出 #1

1
2

说明/提示

数据规模与约定

  • 对于 \(30\%\) 的数据,\(0 \le n\)\(m \le 1000\)
  • 对于 \(100\%\) 的数据,\(0 \le n\)\(m \le 10^5\)

解法&&个人感想

一开始,我们想着能不能直接用区间修改来做这道题,但是没办法
所以,我们要把我们要求的东西转化成要维护的东西
想到,区间的颜色数=\(R\)之前的区间开头数-\(L\)之前的区间结尾数
因此,只需要维护区间的开头和区间的结尾就可以了

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x&(-x))
#define maxn 100005
using namespace std;
struct SegmentTree{
    int l,r,st,fi;
}tree[4*maxn];
int n,m;
int op,x,y;
void build(int x,int l,int r){
    tree[x].l=l;tree[x].r=r;
    if(tree[x].l==tree[x].r){
        tree[x].st=tree[x].fi=0;
        return ;
    }
    int mid=(tree[x].l+tree[x].r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
    tree[x].st=tree[x*2].st+tree[x*2+1].st;
    tree[x].fi=tree[x*2].fi+tree[x*2+1].fi;
    return ;
}
void change_1(int x,int n,int k){
    if(tree[x].l==tree[x].r){
        tree[x].st+=k;
        return ;
    }
    int mid=(tree[x].l+tree[x].r)/2;
    if(n<=mid) change_1(x*2,n,k);
    else change_1(x*2+1,n,k);
    tree[x].st=tree[x*2].st+tree[x*2+1].st;
    return ;
}
void change_2(int x,int n,int k){
    if(tree[x].l==tree[x].r){
        tree[x].fi+=k;
        return ;
    }
    int mid=(tree[x].l+tree[x].r)/2;
    if(n<=mid) change_2(x*2,n,k);
    else change_2(x*2+1,n,k);
    tree[x].fi=tree[x*2].fi+tree[x*2+1].fi;
    return ;
}
int query_1(int x,int l,int r){
    if(l<=tree[x].l&&tree[x].r<=r) return tree[x].st;
    int mid=(tree[x].l+tree[x].r)/2;
    int ans=0;
    if(l<=mid) ans+=query_1(x*2,l,r);
    if(r>mid) ans+=query_1(x*2+1,l,r);
    return ans;
}
int query_2(int x,int l,int r){
    if(l<=tree[x].l&&tree[x].r<=r) return tree[x].fi;
    int mid=(tree[x].l+tree[x].r)/2;
    int ans=0;
    if(l<=mid) ans+=query_2(x*2,l,r);
    if(r>mid) ans+=query_2(x*2+1,l,r);
    return ans;
}
int main(){
    cin>>n>>m;
    build(1,1,n);
    for(int i=1;i<=m;i++){
        cin>>op;
        if(op==1){
            cin>>x>>y;
            change_1(1,x,1);
            change_2(1,y,1);
        }
        else{
            cin>>x>>y;
            int ans_1=query_1(1,1,y);
            int ans_2=query_2(1,1,x-1);
            cout<<ans_1-ans_2<<endl;
        }
    }
    system("pause");
    return 0;
}

后半学期,也请各位继续关注:
《我的青春线代物语果然有问题》
《高数女主养成计划》
《程设の旅》
《青春猪头少年不会梦到多智能体吃豆人》
《某Linux的开源软件》
《Charlotte太空探索》
还有——

《我的算法竞赛不可能这么可爱》

本期到此结束!

posted @ 2025-05-22 08:25  elainafan  阅读(20)  评论(0)    收藏  举报