Turing Tree_线段树&树状数组
Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
3
1 1 4
2
1 2
2 3
5
1 1 2 1 3
3
1 5
2 4
3 5
5
6
3
6
【题意】给出n个数,然后提出m个问题,求区间内不重复的数之和。
【思路】先按查询的右坐标升序排列(保证我查询的改动不会影响到后面查询的结果)。把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。
线段树:
#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long int LL;
const int N=+;
const int M=+;
int n,m;
struct node1
{
int l,r;
LL num; }sum[N*];
struct node
{
int ll,rr,index; }q[M];
bool cmp(node x,node y)//按他的右边界排序
{
return x.rr<y.rr;
}
LL a[N];
map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置
LL ans[M];
void build(int k,int l,int r)//建树
{
sum[k].l=l;
sum[k].r=r;
sum[k].num=;
if(l==r) return ;
int mid=l+r>>;
build(k*,l,mid);
build(k*+,mid+,r);
}
void update(int k,int l,int r,int x,LL v)//更新结点的值
{
if(l==r)
{
sum[k].num+=v;
return ;
}
int mid=l+r>>;
if(x<=mid) update(k*,l,mid,x,v);
else update(k*+,mid+,r,x,v);
sum[k].num=sum[k*].num+sum[k*+].num;
}
LL query(int k,int l,int r,int ll,int rr)//查询区间的值
{
if(l>=ll&&r<=rr)
{
return sum[k].num;
}
int mid=l+r>>;
LL res=;
if(ll<=mid) res+=query(k*,l,mid,ll,rr);
if(rr>mid) res+=query(k*+,mid+,r,ll,rr);
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(,,n);
scanf("%d",&m);
for(int i=;i<m;i++)
{
scanf("%d%d",&q[i].ll,&q[i].rr);
q[i].index=i;
}
sort(q,q+m,cmp);
int k=;
for(int i=;i<m;i++)
{
for(;k<=q[i].rr;k++)
{
if(mp[a[k]]!=) update(,,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去
mp[a[k]]=k;//将位置赋给当前的结点
update(,,n,k,a[k]);//将当前结点更新到树中
}
ans[q[i].index]=query(,,n,q[i].ll,q[i].rr);
}
for(int i=;i<m;i++) printf("%I64d\n",ans[i]);
}
return ;
}
树状数组:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
const int N=+;
int n,m,a[N];
long long sum[N*],ans[N*];
map<int,int >mp;
struct node
{
int l,r,id;
bool operator<(const node &a)const{
if(r==a.r) return l<a.l;
return r<a.r;
}
}q[N*];
int lowbit(int x)
{
return x&(-x);
}
void update(int p,int v)
{
while(p<=n)
{
sum[p]+=v;
p+=lowbit(p);
}
}
long long int query(int p)
{
long long int res=;
while(p)
{
res+=sum[p];
p-=lowbit(p);
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
memset(sum,,sizeof(sum));
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=;i<m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
q[i].l=l;q[i].r=r;q[i].id=i;
}
sort(q,q+m);
int cnt=;
for(int i=;i<=n;i++)
{
if(mp.find(a[i])==mp.end())//在mp中没有找到
{
update(i,a[i]);
mp[a[i]]=i;
}
else
{
update(i,a[i]);
update(mp[a[i]],-a[i]);
mp[a[i]]=i;
}
while(q[cnt].r==i)
{
ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-);
cnt++;
}
}
for(int i=;i<m;i++) printf("%lld\n",ans[i]);
}
return ;
}
Turing Tree_线段树&树状数组的更多相关文章
- CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)
The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...
- HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...
- Hdu-3333 Turning Tree (离线树状数组/线段树)
Hdu-3333 Turning Tree 题目大意:先给出n个数字.面对q个询问区间,输出这个区间不同数的和. 题解:这道题有多重解法.我另一篇博客写了分块的解法 HDU-3333 Turing ...
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- HDU 1556 线段树或树状数组,插段求点
1.HDU 1556 Color the ball 区间更新,单点查询 2.题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次. (1)树状数组 总结:树状数组是一个查 ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
随机推荐
- ASP.NET Core + EF6
微软推出了全新的 .Net Core,于是我就想着在目前接手的项目中使用这项新技术.但是因为预算的原因,我们所用的数据库是 MySql .但是最新的 EF Core 并不支持 MySql ,所以目前我 ...
- JAVA-Semaphore信号灯-可实现维护自身线程访问数
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex ...
- Number To Indian Rupee Words in Oracle Forms / Reports
Convert numbers to Indian Rupees format in Oracle Forms / Reports.Create the below mention function ...
- iOS - C 应用
前言 1)操作符两端必须加空格,(每行第一个赋值语句对齐). 2)变量名必须是英文(不能是拼音):英文.数字.下划线和美元符号. 3)等于号 == 反过来写(0 == i%4)防止少些赋值号的错误. ...
- zoj3228Searching the String(ac自动机)
链接 这个题把病毒分为了两种,一种包含可以覆盖,另一种不可以,需要分别求出包含他们的个数,可以把两种都建在一颗tire树上,在最后求得时候判断一下当前节点是属于哪种字符串,如果是不包含的需要判断一下p ...
- css学习笔记 1
对于一个页面,如何控制页面的结构就看如何去理解css的各个属性了,只有了解了css的各个属性后才能更有效的让css控制页面的任何一个结构. css的结构:选择符:{属性名1:属性值; 属性名2:属性值 ...
- Sprint2-3.0
后续安排 第16周 周二晚7点之前将本代码上传到GITHUB. GITHUB地址:https://github.com/QueenIcey/teamwork/tree/master/eslife1 周 ...
- VB6.0对鼠标滚轮不支持的解决方法[转]已经测试work
今天要修改一个老DLL文件,安装了vb6,用起来很不爽. VB6编辑器 和 VBA编辑器 (Office 中的VB编辑器)都不支持鼠标滚动. 但 MS 已经提供了补丁http://download.m ...
- Validate Binary Search Tree [LeetCode]
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- Minimum Path Sum [LeetCode]
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...