生活随笔
收集整理的這篇文章主要介紹了
洛谷 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.
第一行為兩個整數(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ù)。 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ù)。 下面舉個例子,如圖:
#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)容還不錯,歡迎將生活随笔 推薦給好友。