刚看到是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(线段树+离散化)的更多相关文章

  1. HDU 3333 Turing Tree 线段树+离线处理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...

  2. HDU 3333 Turing Tree (线段树)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)

    题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...

  4. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  5. HDU 3333 Turing Tree (主席树)

    题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...

  6. hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)

    http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others)    ...

  7. HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改

    题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...

  8. HDU 3333 Turing Tree(离线树状数组)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  9. HDU - 1542 扫描线入门+线段树离散化

    扫描线算法+线段树维护简介: 像这种求面积的并集的题目,就适合用扫描线算法解决,具体来说就是这样 类似这种给出点的矩形的对角的点的坐标,然后求出所有矩形面积的交集的问题,可以采用扫描线算法解决.图如下 ...

随机推荐

  1. 高速掌握sinox2014激动人心的ZFS和RAID技术

    Sinox2014引入激动人心的zfs系统以及其支持的RAID,让用户高速打造便宜的高可靠性文件server. ZFS文件系统的英文名称为Zettabyte File System,也叫动态文件系统( ...

  2. Cocos2d-x Lua 阅读Csv文件,使用数据更方便

    在我的书或出售之前,我的源代码,有Csvshadow文件. 也许这是偏见.我与工作将是最长的轮廓Csv,所以,我会帮助不大喜欢它的游戏. Csv文件,非常格式easy,也就是说,一个数据线,字段之间用 ...

  3. Android使用OpenGL ES2.0显示YUV,您的手机上的数据要解决两个方面的坐标

    如果说 ,我不知道,如果你不明白这个话题.连接到:http://blog.csdn.net/wangchenggggdn/article/details/8896453(下称链接①), 里面评论有非常 ...

  4. PHP中遍历stdclass object 及 json

    原文:PHP中遍历stdclass object 及 json (从网上找的模拟实例)需要操作的数据: $test=Array ( [0] => stdClass Object ( [tags] ...

  5. Spring之SpringMVC的Controller(源码)分析

    说明: 例子就不举了,还是直接进入主题,本文主要是以SpringMVC的Controller接口为入点,来分析SpringMVC中C的具体实现和处理过程. 1.Controller接口 public ...

  6. OpenSUSE13.2安装MongoDB

    真是一个悲伤的故事,就是你解决过得问题没有记住,却需要再通过搜索引擎来找一遍,幸运的是曾经你做过记录,搜索帮你找到了. 这是我一个Wordpress博客整理记录的,好久没在那里更新了,两个月的时间,我 ...

  7. 探秘IntelliJ IDEA 13中的版本控制——Subversion 1.8

    IntelliJ IDEA 中引入的重要特性就是版本控制,而在IntelliJ IDEA 13中的体现便是支持最新的Subversion 1.8. 相对于之前版本对Subversion的支持,Subv ...

  8. SQL SERVER – Import CSV File Into SQL Server Using Bulk Insert – Load Comma Delimited File Into SQL Server

    CSV stands for Comma Separated Values, sometimes also called Comma Delimited Values. Create TestTabl ...

  9. 学习html5的WebSocket连接

    1.什么是WebSocket WebSocket 是一种自然的全双工.双向.单套接字连接.使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSo ...

  10. ASP.NET DataTable的操作大全

    DataTable表示一个与内存有关的数据表,可以使用工具栏里面的控件拖放来创建和使用,也可以在编写程序过程中根据需要独立创建和使用,最常见的情况是作为DataSet的成员使用,在这种情况下就需要用在 ...