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 ...
随机推荐
- treegrid and datagrid ctrl or shift selectRow
var tg = $('#tg');tg.treegrid({...}); // create treegridvar panel = tg.treegrid('getPanel');var body ...
- c语言头文件中定义全局变量的问题
c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...
- jQuery 效果 —— 滑动
jQuery 效果 -- 滑动 1.向下滑动元素 (1)使用slideDown()方法可以用于向下滑动元素 $("button").click(function(){ $(&quo ...
- <转>修改TM2013聊天记录保存目录final版
一直很钟意TM的清爽,然而在升级到TM2013 preview1后,发生了一件很让人头痛的事. 那就是无法设定消息目录,TM会默认为保存在我的文档下.这让使用dropbox同步聊天记录的我感到十 ...
- CentOS7 增加tomcat 启动,停止,使用systemctl进行配置
1,centos7 使用 systemctl 替换了 service命令 参考:redhat文档: https://access.redhat.com/documentation/en-US/Red_ ...
- SQL Syntax
1.limit 语法:限制查询记录,进行分页处理:select * from article limit 0,10;(从0号记录开始,依次取10条记录) 2.like 语法:查询指定字符串的相似匹配记 ...
- selenium 安装与 chromedriver安装
直接使用pip安装 pip slenium 用 Chrome 浏览器来测试 from selenium import webdriver browser = webdriver.Chrome() ...
- python无意中发现的
http://www.zhihu.com/question/37904398?sort=created&page=2 >>> a = [[1,2],[3,4],[5,6,7] ...
- NOIP系列复习及题目集合
首先是我的酱油记了啦~: Xs的NOIP2014酱油记,持续更新中 知识点方面: noip知识点总结之--贪心 noip知识点总结之--线性筛法及其拓展 noip知识点总结之--欧几里得算法和扩展欧几 ...
- iOS开发UI篇—手写控件,frame,center和bounds属性
iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...