hdu 3333 Turing Tree(线段树+离散化)
刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望。
刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的。
前两天我在做一道题的时候,也是因为数据范围太大(同样是1000000000)不能打表,当时想了许久,想到把这些数值存进一个数组里面,对这个数组进行排序,然后对于其中的某个值可以进行二分查找。今天我又长姿势了,原来这种方法叫做离散化。
刚开始我想着可以把那些相同的值用0去替代,但是一个解决不了的问题是如果把两个相同的值其中一个改为0,那么如果问题区间刚好包含这个值不包含另一个值该怎么处理,甚至如果问题区间问的就是这个值,那该怎么办。
苦思良久也没想到什么好办法。看了下别人的思路,是将所有的问题区间放在一起,以区间的右边界为关键字进行排序,然后对于线段树的值边插入边更新,具体思路见代码。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100005
#define M 30005
struct node
{
int x,y;
int id;
}Q[N];
struct tree
{
int x,y;
__int64 sum;
}a[M*3];
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int cmp1(const void *a,const void *b)
{
node *c;
node *d;
c=(node *)a;
d=(node *)b;
return c->y-d->y;
}
int visit[M],temp[M],tem[M],b[M];
__int64 ans[N];
void CreatTree(int t,int x,int y)
{
a[t].x=x;
a[t].y=y;
a[t].sum=0;
if(x==y)
return ;
int temp=t*2;
int mid=(x+y)/2;
CreatTree(temp,x,mid);
CreatTree(temp+1,mid+1,y);
return ;
}
void InsertTree(int t,int x,int y)
{
if(a[t].x==a[t].y)
{
a[t].sum+=y;
return ;
}
int temp=t*2;
int mid=(a[t].x+a[t].y)/2;
if(x<=mid)
InsertTree(temp,x,y);
else
InsertTree(temp+1,x,y);
a[t].sum=a[temp].sum+a[temp+1].sum;
return ;
}
__int64 FindTree(int t,int x,int y)
{
if(a[t].x==x&&a[t].y==y)
return a[t].sum;
int temp=t*2;
int mid=(a[t].x+a[t].y)/2;
__int64 sum;
sum=0;
if(y<=mid)
sum+=FindTree(temp,x,y);
else if(x>mid)
sum+=FindTree(temp+1,x,y);
else
{
sum+=FindTree(temp,x,mid);
sum+=FindTree(temp+1,mid+1,y);
}
return sum;
}
int Find(int x,int k)
{
int l,r,mid;
l=1;
r=k;
while(l<=r)
{
mid=(l+r)/2;
if(temp[mid]>x)
r=mid-1;
else if(temp[mid]<x)
l=mid+1;
else
return mid;
}
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
CreatTree(1,1,n);
int i,j,k;
j=0;
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
tem[j++]=b[i];
}
qsort(tem,j,sizeof(tem[0]),cmp);
k=0;
temp[0]=tem[0];
for(i=1;i<j;i++)
{
if(tem[i]!=temp[k])
{
k++;
temp[k]=tem[i];
}
}
memset(visit,0,sizeof(visit));
int m;
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&Q[i].x,&Q[i].y);
Q[i].id=i;
}
qsort(Q+1,m,sizeof(Q[0]),cmp1);
j=1;
for(i=1;i<=n;i++)
{
int flag;
int id;
id=Find(b[i],k);
flag=visit[id];
if(flag)
InsertTree(1,flag,-b[i]);
InsertTree(1,i,b[i]);
visit[id]=i;
for(;j<=m;j++)
{
if(i==Q[j].y)
{
__int64 tt;
tt=FindTree(1,Q[j].x,Q[j].y);
ans[Q[j].id]=tt;
}
else
break;
}
}
for(i=1;i<=m;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}
hdu 3333 Turing Tree(线段树+离散化)的更多相关文章
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...
- HDU 3333 Turing Tree(树状数组/主席树)
题意 给定一个长度为 \(n\) 的序列,\(m\) 个查询,每次查询区间 \([L,R]\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...
- HDU 3333 Turing Tree (主席树)
题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...
- hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)
http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others) ...
- HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...
- HDU 3333 Turing Tree(离线树状数组)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU - 1542 扫描线入门+线段树离散化
扫描线算法+线段树维护简介: 像这种求面积的并集的题目,就适合用扫描线算法解决,具体来说就是这样 类似这种给出点的矩形的对角的点的坐标,然后求出所有矩形面积的交集的问题,可以采用扫描线算法解决.图如下 ...
随机推荐
- [译]在运行时内存中的Java对象是怎么样的
(文章翻译自What do Java objects look like in memory during run-time?) 我们知道函数在内存中是作为一个活动记录栈来实现的.而且我们知道Java ...
- [译]Java垃圾回收是如何工作的
说明:这篇文章来翻译来自于Javapapers 的How Java Garbage Collection Works 这部分教程是为了理解Java垃圾回收的基础以及它是如何工作的.这是垃圾回收系列教程 ...
- leetcode[55] Merge Intervals
题目:给定一连串的区间,要求输出不重叠的区间. Given a collection of intervals, merge all overlapping intervals. For exampl ...
- 利用PL/SQL Developer工具导出数据到excel,导入excel数据到表
使用PL/SQL Developer工具. 导出: 1.执行select 语句查询出需要导出的数据. 2.在数据列表中右键,选择save results.保存为.csv文件,然后已excel方式打开就 ...
- Android有关Volley使用(十)至Request和Reponse意识
我们知道,.网络Http沟通,会有一个Request,相同,也将有Response.我们Volley在使用RequestQueue来之前加入的请求.我们将创建一个Request对象,例StringRe ...
- win7 64位下如何安装配置mysql-5.7.7-rc-winx64
距离上次安装MySQL已经过去好久了.步骤这些,有可能会忘记.简单记录一下吧.(参考了一些网络上的博客.) 1.mysql-5.7.5-m15-winx64.zip下载 官方网站下载地址: http: ...
- Confluence, JIRA, Fisheye
[tools]迁移Confluence, JIRA, Fisheye [背景] 原先的Confluence, JIRA, Fisheye都部署在一台服务器(192.168.200.203)上,导致 ...
- Hadoop作业提交之TaskTracker获取Task
[Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ...
- android通过程序收起通知栏
1. 添加权限 <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> 2. ...
- IEnumerable实践应用
1.集合想要支持foreach方式遍历,需要返回一个迭代器(IEnumerator),foreach会自动调用迭代器的状态迁移(MoveNext().Curent.Reset()) #region A ...