首页 > 编程语言 >hdu 3874(树状数组+离线算法)

hdu 3874(树状数组+离线算法)

时间:2023-05-29 22:36:39浏览次数:50  
标签:tmp hdu int 离线 3874 mid include size


解题思路:这道题和之前的题一样,查找[l,r]区间内不重复数字的和。可以利用离线算法,实际上离线算法为了解决在查找时出现的矛盾,因为每次询问的区间大小不同,如果单独处理的话可能会对之后的查询有影响,所以离线算法帮助我们把要查询的区间先按照右端点进行排序,因为在处理更靠右的区间时,比它小的区间肯定是已经得到的不重复的数了,所以不会影响到后面的查找。



#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int M = 200005;
const int N = 50005;
struct Query
{
	int l,r,id;
	
	bool operator < (Query a)
	{
		return r < a.r;
	}
}q[M];
int n,m,size;
int tree[N<<1],arr[N],tmp[N],last[N],ans[M];

int lowbit(int x)
{
	return x & -x;
}

void update(int x,int d)
{
	for(int i = x; i <= n; i += lowbit(i))
		tree[i] += d;
}

int getsum(int x)
{
	int sum = 0;
	for(int i = x; i > 0; i -= lowbit(i))
		sum += tree[i];
	return sum;
}

int bisearch(int val)
{
	int l = 1, r = size, mid;
	while(l <= r)
	{
		mid = (l + r) >> 1;
		if(tmp[mid] == val) return mid;
		else if(tmp[mid] > val)
			r = mid - 1;
		else l = mid + 1;
	}
}

int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		cin >> n;
		for(int i = 1; i <= n; i++)
		{
			cin >> arr[i];
			tmp[i] = arr[i];
		}
		cin >> m;
		for(int i = 1; i <= m; i++)
		{
			cin >> q[i].l >> q[i].r;
			q[i].id = i;
		}
		sort(tmp+1,tmp+1+n);
		sort(q+1,q+1+m);
		//离散化
		size = 1;
		for(int i = 2; i <= n; i++)
			if(tmp[i] != tmp[i-1])
				tmp[++size] = tmp[i];
		memset(tree,0,sizeof(tree));
		memset(last,0,sizeof(last));
		int idx = 1;
		for(int i = 1; i <= n; i++)
		{
			int x = bisearch(arr[i]);
			if(last[x])
				update(last[x],-arr[i]);
			update(i,arr[i]);
			last[x] = i;
			while(q[idx].r == i && idx <= m)
			{
				ans[q[idx].id] = getsum(q[idx].r) - getsum(q[idx].l - 1);
				idx++;
			}
		}
		for(int i = 1; i <= m; i++)
			cout << ans[i] << endl;
	}
	return 0;
}




标签:tmp,hdu,int,离线,3874,mid,include,size
From: https://blog.51cto.com/u_16143128/6374311

相关文章

  • hdu 4101(bfs+博弈)
    题意:题目的意思就是说两个人轮流玩游戏,给你一张地图,这个地图中间有一点-1代表宝藏,AliandBaba轮流走路,如果某一个人能够直接走到宝藏的话,那么他就赢了。地图上其它的点0代表空地,数字代表当前地点的石子当某一人拿石子的时候,他只能拿走一颗。问你谁最后能拿到宝藏;解题思路:宝藏位于-......
  • hdu 1510
    WhiteRectanglesTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)ProblemDescriptionYouaregivenachessboardmadeupofNsquaresbyNsquareswithequalsize.Someofthesquaresarecoloredblack,andthe......
  • hdu 2821
    题意:n*m的格子上有一些方块放在某些格子上,一个格子可能有几个方块,用'a'-'z'来表示方块数量。初始的时候可以选择任意空地作为Pusher初始点,Pusher选择一个方向,然后向这个方向前进直到遇到有方块的格子,Pusher把这个格子的方块清除一个,并把它向前推一格(向前不能出界),如果前面一格有方......
  • hdu 1534(差分约束)
    题意:安排计划,有4种约束方式,给出你这些时间的n个约束..如果计划是可行的,求出每一件事发生的最早时间..否则输出“impossible”..①.FAFaba要在b完成后完成..②.FASaba要在b开始前完成..③.SASaba要在b开始前开始..④.SAFaba要在b结束前开......
  • hdu 1532(最大流)
    解题思路:这是一道典型的模板题,直接套用EK算法即可。。。我感觉最大流的本质就是能否找到一个从源点到汇点的增广路径,并将其最小的边作为增加值,沿着增广路上的边进行更新。AC:#include<iostream>#include<cstdio>#include<cstring>#include<queue>usingnamespacestd;consti......
  • hdu 5074(简单dp)
    HatsuneMikuTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:262144/262144K(Java/Others)ProblemDescriptionHatsuneMikuisapopularvirtualsinger.ItisverypopularinbothJapanandChina.Basicallyitisacomputersoftwarethata......
  • hdu 3303(线段树+抽屉原理)
    解题思路:这题利用了抽屉原理,即1-M之间的所有数与M+1的模都不相同。那么可以利用它将要查找所有区间分成[1,Y-1],[Y,2*Y-1],[2*Y,3*Y-1].........一直下去,直到所有的区间都被找一遍,然后就是保存最小的模即可。。。这样就肯定要找每个区间的最小的模,实际上这里可以利用线段树去找,只需......
  • hdu 4417(树状数组+离线算法)
    解题思路:这道题要求某区间内比h小的个数,其实这里可以类似于树状数组求逆序数那样。关键是如何转换成树状数组的模型,这才是本题的难点。我们首先分析,如果知道h在该区间的哪个位置,那么剩下的就很好做了。我们还可以发现,如果找到了当前的比h小的所有点(大于的点我们先忽略掉),那么我们就......
  • hdu 3681(bfs+dfs+状态压缩)
    解题思路:这道题属于图上来回走的问题,可以把重复走的过程弱化,即只强调从u->v的结果,中间经过的节点都不考虑。这道题里面'G','F','Y'是重要的节点,其余的点我们是可以忽略的,也就是说,假设从u->v,我们只需要知道最短路径是多少就可以了,至于是怎么走的,中间绕过了多少个'D'都不是我们关心的......
  • hdu 4012(bfs+位压缩)
    思路:每次涂色以后必有一个格子的颜色是最终的颜色,否则这次涂色根本没意义,所以我们把每次涂色后哪些格子成为最终颜色的所有可能都入队,入队的元素是一个struct包含步数和最终颜色已确定的木块集合,这个集合必须用整数表示,所以用到状态压缩,因为最多只有16个格子,所以用16位的二进制来表......