HDU 3874 Necklace&&HDU 3333 Turing Tree(求一些区间l~r中的数去重后的和)
2017-08-01 11:29
513 查看
题目意思
题目意思:告诉你一些数,然后让你求一些区间l~r中的数去重后的和
思路:预处理全部的查询,通过每个查询区间的右边界排序,每次更新一个值,如果之前更新过就这个数就把之前的位置上的该值给删掉,再在现在的位置添加这个值。
题目地址
题意&思路:就是数据范围变大了,用map去替代vis数组存是否访问过该值,以及位置就好了
题目意思:告诉你一些数,然后让你求一些区间l~r中的数去重后的和
思路:预处理全部的查询,通过每个查询区间的右边界排序,每次更新一个值,如果之前更新过就这个数就把之前的位置上的该值给删掉,再在现在的位置添加这个值。
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define N 50010 #define M 200010 #define K 1000010 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 using namespace std; const LL mod = 1e9 + 7; const double eps = 1e-9; struct node { LL sum; }sum[N << 2];//线段树主体 struct nope { int l, r, id; }fw[M]; int num ; LL cnt[M]; int vis[K]; bool cmp(nope a, nope b) { return a.r < b.r; } struct Segment__Tree { int x, y; void pushUp(int ans) { sum[ans].sum = sum[ans << 1].sum + sum[ans << 1 | 1].sum; } void build(int l, int r, int ans) { if (l == r) { sum[ans].sum = 0; return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(ans); } LL solve(int l, int r, int ans) { if (l >= x&&r <= y) { return sum[ans].sum; } int mid = (l + r) >> 1; if (mid<x) { return solve(rson); } else if (mid >= y) { return solve(lson); } else { return solve(lson) + solve(rson); } } void updata(int l, int r, int ans, int kk, int nums) { if (l == r) { sum[ans].sum += nums; return; } int mid = (l + r) >> 1; if (mid >= kk) { updata(lson, kk, nums); } else { updata(rson, kk, nums); } pushUp(ans); } }; int main() { cin.sync_with_stdio(false); int n, q; int T; Segment__Tree tree; cin >> T; while (T--) { cin >> n; for (int i = 1; i <= n; i++) { cin >> num[i]; } tree.build(1, n, 1); cin >> q; for (int i = 1; i <= q; i++) { cin >> fw[i].l >> fw[i].r; fw[i].id = i; } sort(fw + 1, fw + q + 1, cmp); int ll = 1; memset(vis, -1, sizeof(vis)); for (int i = 1; i <= q; i++) { while (ll <= fw[i].r) { if (vis[num[ll]] != -1) { tree.updata(1, n, 1, vis[num[ll]], -num[ll]); } vis[num[ll]] = ll; tree.updata(1, n, 1, ll, num[ll]); ll++; } tree.x = fw[i].l; tree.y = fw[i].r; cnt[fw[i].id] = tree.solve(1, n, 1); } for (int i = 1; i <= q; i++) { cout << cnt[i] << endl; } } return 0; }
题目地址
题意&思路:就是数据范围变大了,用map去替代vis数组存是否访问过该值,以及位置就好了
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define N 50010 #define M 200010 #define K 1000010 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 using namespace std; const LL mod = 1e9 + 7; const double eps = 1e-9; struct node { LL sum; }sum[N << 2];//线段树主体 struct nope { int l, r, id; }fw[M]; LL num ; LL cnt[M]; map<LL,int> vis; bool cmp(nope a, nope b) { return a.r < b.r; } struct Segment__Tree { int x, y; void pushUp(int ans) { sum[ans].sum = sum[ans << 1].sum + sum[ans << 1 | 1].sum; } void build(int l, int r, int ans) { if (l == r) { sum[ans].sum = 0; return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(ans); } LL solve(int l, int r, int ans) { if (l >= x&&r <= y) { return sum[ans].sum; } int mid = (l + r) >> 1; if (mid<x) { return solve(rson); } else if (mid >= y) { return solve(lson); } else { return solve(lson) + solve(rson); } } void updata(int l, int r, int ans, int kk, LL nums) { if (l == r) { sum[ans].sum += nums; return; } int mid = (l + r) >> 1; if (mid >= kk) { updata(lson, kk, nums); } else { updata(rson, kk, nums); } pushUp(ans); } }; int main() { cin.sync_with_stdio(false); int n, q; int T; Segment__Tree tree; cin >> T; while (T--) { cin >> n; for (int i = 1; i <= n; i++) { cin >> num[i]; } tree.build(1, n, 1); cin >> q; for (int i = 1; i <= q; i++) { cin >> fw[i].l >> fw[i].r; fw[i].id = i; } sort(fw + 1, fw + q + 1, cmp); int ll = 1; vis.clear(); for (int i = 1; i <= q; i++) { while (ll <= fw[i].r) { if (vis.find(num[ll]) != vis.end()) { tree.updata(1, n, 1, vis[num[ll]], -num[ll]); } vis[num[ll]] = ll; tree.updata(1, n, 1, ll, num[ll]); ll++; } tree.x = fw[i].l; tree.y = fw[i].r; cnt[fw[i].id] = tree.solve(1, n, 1); } for (int i = 1; i <= q; i++) { cout << cnt[i] << endl; } } return 0; }
相关文章推荐
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
- hdu 3333 Turing Tree & hdu 3874 Necklace (成段更新)
- hdu 3874 Necklace 线段树单点更新区间求和
- HDU 3874 Necklace 区间查询的离线操作
- HDU 3333&&HDU-3874 Necklace 离线树状数组
- hdu 3333 Turing Tree 线段树 离线查询(区间内不同的数之和)
- 【HDU 3333】【离线询问 树状数组 前驱思想】Turing Tree【 求区间中不同的数的和】
- HDU 3333 & 3874 (线段树+离线询问)
- HDU 3874 Necklace(线段树啊 单点更新 区间求和)
- hdu 3874 Necklace(bit树+事先对查询区间右端点排序)
- hdu 3874 Necklace 求数组任意区间和(相同元素只算一次) 树状数组+离线算法
- HDU 3333 & 3874 (线段树+离线询问)
- hdu 3333 Turing Tree(线段树求区间内不同值之和+离线处理)
- HDU 3874 Necklace (线段树单点更新+区间查询+离线操作)
- HDU 3308 LCIS (线段树·单点更新·区间合并)
- 【hdu】Mayor's posters(线段树区间问题)
- HDU 3333 Turing Tree
- hdu 3874 Necklace 线段树
- http://acm.hdu.edu.cn/showproblem.php?pid=1754&&线段树区间求最值
- FJUT 3097(hdu 3333) 区间种类数 线段树+离线