日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

洛谷 P2184 贪婪大陆

發(fā)布時間:2023/12/18 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷 P2184 贪婪大陆 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

洛谷 P2184 貪婪大陸

Description

  • 小FF最后一道防線是一條長度為N的戰(zhàn)壕, 小FF擁有無數(shù)多種地雷,而SCV每次可以在[ L , R ]區(qū)間埋放同一種不同于之前已經(jīng)埋放的地雷。 由于情況已經(jīng)十萬火急,小FF在某些時候可能會詢問你在[ L' , R'] 區(qū)間內(nèi)有多少種不同的地雷, 他希望你能盡快的給予答復(fù)。

    對于30%的數(shù)據(jù): 0<=n, m<=1000;

    對于100%的數(shù)據(jù): 0<=n, m<=10^5.

Input

  • 第一行為兩個整數(shù)n和m; n表示防線長度, m表示SCV布雷次數(shù)及小FF詢問的次數(shù)總和。

    接下來有m行, 每行三個整數(shù)Q,L , R; 若Q=1 則表示SCV在[ L , R ]這段區(qū)間布上一種地雷, 若Q=2則表示小FF詢問當(dāng)前[ L , R ]區(qū)間總共有多少種地雷。

Output

  • 對于小FF的每次詢問,輸出一個答案(單獨一行),表示當(dāng)前區(qū)間地雷總數(shù)。

Sample Input

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

Sample output

1

2

題解:

  • 數(shù)據(jù)結(jié)構(gòu)題(線段樹)
  • 這題再一次告訴了我線段樹的靈活。記住,線段樹不是一種算法,而是一種數(shù)據(jù)結(jié)構(gòu)。是用來維護(hù)區(qū)間的,至于怎么維護(hù),要結(jié)合題意。這題求的是種類。所以如果維護(hù)和/最值肯定不行。所以要換一種思路。對于每次給出的埋地雷區(qū)間[l, r],l為開始標(biāo)記,r為結(jié)束標(biāo)記。開兩個線段樹,分別在l和r單點修改。最后區(qū)間[l, r]的結(jié)果就是1-r的開始標(biāo)記個數(shù) - 1-(l - 1)的結(jié)束標(biāo)記個數(shù)。
  • 下面舉個例子,如圖:

  • 紅色為開始標(biāo)記,綠色為結(jié)束標(biāo)記。
  • 首先查詢1-r的開始標(biāo)記個數(shù),意味著有這么多個地雷
  • 然后查詢1-(l - 1)的結(jié)束標(biāo)記個數(shù),意味著到查詢區(qū)間之前已經(jīng)有兩種地雷埋完了
  • 為什么不查查詢區(qū)間里的結(jié)束標(biāo)記,因為如果在查詢區(qū)間里結(jié)束,地雷區(qū)間還是覆蓋到了一部分的查詢區(qū)間

  • 這道題挺巧妙的,需要反復(fù)琢磨

#include <iostream> #include <cstdio> #define maxn 100005 using namespace std;struct Tree {int l, r, val, tag;} tree1[maxn * 4], tree2[maxn * 4]; int n, m;int read() {int x = 0; char c = getchar();while(c < '0' || c > '9') c = getchar();while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}return x; }void build(int root, int l, int r) {tree1[root].l = tree2[root].l = l, tree1[root].r = tree2[root].r = r;if(l == r) return;int mid = (l + r) >> 1;build(root << 1, l, mid), build(root << 1 | 1, mid + 1, r); }void down1(int root) {int son1 = root << 1, son2 = root << 1 | 1;tree1[son1].tag += tree1[root].tag, tree1[son2].tag += tree1[root].tag;tree1[son1].val += (tree1[son1].r - tree1[son1].l + 1) * tree1[root].tag;tree1[son2].val += (tree1[son2].r - tree1[son2].l + 1) * tree1[root].tag;tree1[root].tag = 0; }void down2(int root) {int son1 = root << 1, son2 = root << 1 | 1;tree2[son1].tag += tree2[root].tag, tree2[son2].tag += tree2[root].tag;tree2[son1].val += (tree2[son1].r - tree2[son1].l + 1) * tree2[root].tag;tree2[son2].val += (tree2[son2].r - tree2[son2].l + 1) * tree2[root].tag;tree2[root].tag = 0; }void update1(int root, int l, int r, int add) {if(tree1[root].l >= l && tree1[root].r <= r){tree1[root].tag += add;tree1[root].val += (tree1[root].r - tree1[root].l + 1) * add;return;}if(tree1[root].tag) down1(root);int mid = (tree1[root].l + tree1[root].r) >> 1;if(l <= mid) update1(root << 1, l, r, add);if(r > mid) update1(root << 1 | 1, l, r, add);tree1[root].val = tree1[root << 1].val + tree1[root << 1 | 1].val; }void update2(int root, int l, int r, int add) {if(tree2[root].l >= l && tree2[root].r <= r){tree2[root].tag += add;tree2[root].val += (tree2[root].r - tree2[root].l + 1) * add;return;}if(tree2[root].tag) down2(root);int mid = (tree2[root].l + tree2[root].r) >> 1;if(l <= mid) update2(root << 1, l, r, add);if(r > mid) update2(root << 1 | 1, l, r, add);tree2[root].val = tree2[root << 1].val + tree2[root << 1 | 1].val; }int ask1(int root, int l, int r) {if(tree1[root].l >= l && tree1[root].r <= r) return tree1[root].val;if(tree1[root].tag) down1(root);int mid = (tree1[root].l + tree1[root].r) >> 1, ans = 0;if(l <= mid) ans += ask1(root << 1, l, r);if(r > mid) ans += ask1(root << 1 | 1, l, r);return ans; }int ask2(int root, int l, int r) {if(tree2[root].l >= l && tree2[root].r <= r) return tree2[root].val;if(tree2[root].tag) down2(root);int mid = (tree2[root].l + tree2[root].r) >> 1, ans = 0;if(l <= mid) ans += ask2(root << 1, l, r);if(r > mid) ans += ask2(root << 1 | 1, l, r);return ans; }int main() {cin >> n >> m;build(1, 1, n);for(int i = 1; i <= m; i++){int op = read(), l = read(), r = read();if(op == 1) update1(1, l, l, 1), update2(1, r, r, 1);else printf("%d\n", ask1(1, 1, r) - ask2(1, 1, l - 1));}return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/BigYellowDog/p/11156424.html

總結(jié)

以上是生活随笔為你收集整理的洛谷 P2184 贪婪大陆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。