您的位置:首页 > 其它

HDU 3874 Necklace&&HDU 3333 Turing Tree(求一些区间l~r中的数去重后的和)

2017-08-01 11:29 513 查看
题目意思

题目意思:告诉你一些数,然后让你求一些区间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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: