hdu 4288 Coder (線段樹)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4288


題意:對一個集合,更確切地說是數組吧,第步有三種操作:1、添加一個數x,2、刪除一個數x,3、詢問數組中下標index對5取餘爲3的所有無素的和。

添加一個數時,保證集合中不含此數,同樣刪除時保證含有此數。


解析:這道題目需要維護5顆線段樹,sum[ 5 ]分別表示區間內下標模5爲i的所有元素的和,cnt[ ]是統計該區間內現存操作數的個數,先預讀所有操作,統計一下數據,可以確定建樹的規模。


如果還不是很清楚維護該區間內模5所有情況的和的話,這裏再說一下,想要得到該區間內所有模5等3所有元素的和,左孩子可以求到,兩個孩子相互獨立,所以求右孩子需要知道含有多少個元素,因爲這樣分開求的時候,我們才知道求右孩子時應該求下標模5等幾(==index)的所有元素的和,index在整個數組中下標模5等3,好了,說的真夠咬嘴。。。就是這個意思了


參考代碼:

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

typedef __int64 LL;
const int N = 100050;

struct segment_tree{
	int cnt,lson,rson;
	LL sum[5];
}T[N*4];
int pos,k;

int build(int l,int r)
{
	if(l == r) return pos++;
	int mid = (l+r) / 2,p = pos++;
	T[p].lson = build(l,mid);
	T[p].rson = build(mid+1,r);
	return p;
}

char str[N];
int num[N],op[N],total;

void update(int l,int r,int p,int root)
{
	T[root].cnt += 2 * k - 1;  // 添加或刪除元素個數
	if(l == r)
	{
		T[root].sum[0] = num[p]*k; // 添加或刪除元素
		return ;
	}
	int mid = (l+r)/2;
	if(p <= mid) update(l,mid,p,T[root].lson);
	else update(mid+1,r,p,T[root].rson);
	for(int i = 0;i < 5;++i)  // 更新該區間內模5所有情況的和
		T[root].sum[i] = T[ T[root].lson ].sum[i] + T[ T[root].rson ].sum[((i-T[ T[root].lson ].cnt)%5+5)%5 ];
}

int main()
{
	int n;
	while(scanf("%d",&n) != EOF)
	{
		memset(T,0,sizeof(T));
		pos = 0;
		total = 0;
		for(int i = 0;i < n;++i)
		{
			scanf("%s",str+i);
			if(str[i] != 's')
			{
				scanf("%d",&num[total]);
				op[i] = num[total++];
			}
		}
		sort(num,num+total);
		int max_n = unique(num,num+total) - num; // 去重並統計操作數個數
		build(0,max_n);
		for(int i = 0;i < n;++i)
		{
			if(str[i] == 's') 
			{
				printf("%I64d\n",T[0].sum[2]);
				continue;
			}
			int p = lower_bound(num,num+max_n,op[i]) - num;  // 二分查找該操作數的位置,以確定該操作數在線段樹中的位置
			if(str[i] == 'a') k = 1,update(0,max_n,p,0);  // k的值是在實現添加或刪除元素時的巧妙使用
			else if(str[i] == 'd') k = 0,update(0,max_n,p,0);
		}
	}
	return 0;
}


發佈了74 篇原創文章 · 獲贊 33 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章