HDU4288 – Coder(线段树+离线+离散化)

题目链接:HDU4288

【题意】给出三种操作维护一个值单调增的序列:

add x:向序列添加一个元素x(保证序列中没有x);

del x:删除元素x(保证序列中有x);

sum:求出序列中HDU4288的值

【分析】一开始用splay结果写超时了,然后看题解才知道能用线段树离线搞;把所有add中的x不重复的记录并排序,这样就确定了整个线段树的大小,然后只要用sum[][5]存当前区间中所有%5后的位置的合,sum操作就是输出sum[根][3]的值,add和del需要更新线段树,

关键是push_up();其实只要加一个cnt维护当前区间存在的元素个数,所有左儿子没有偏移,直接sum[u][i] = sum[l][i],关键是右儿子,观察可以发现sum[u][(i+cnt[l])%5] += sum[r][i];

【AC CODE】1326ms

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define id(x,y) (x+y|x!=y)
const int INF = 0x3f3f3f3f, MAXN = 100000+10;
int in[MAXN], add[MAXN],tol, cnt[MAXN<<1];
LL sum[MAXN<<1][5];
map<int,int> num;

void push_up(int x, int y, int m)
{
	int u = id(x,y),l = id(x,m), r = id(m+1,y);
	cnt[u] = cnt[l]+cnt[r];
	rep(i,0,5) sum[u][i] = sum[l][i];
	rep(i,0,5) sum[u][(i+cnt[l])%5] += sum[r][i];
}
int p;
LL v;
void update(int x, int y)
{
	if(x == y)
	{
		sum[id(x,y)][1] += v;
		cnt[id(x,y)] = v > 0;
		return;
	}
	int m = (x+y)>>1;
	if(p <= m) update(x,m);
	else update(m+1,y);
	push_up(x,y,m);
}
int main()
{
#ifdef SHY
	freopen("e:\\1.txt", "r", stdin);
#endif
	int q;
	while(~scanf("%d%*c", &q))
	{
		char op[10];
		int m = 0;
		rep(i,0,q)
		{
			scanf("%s", op);
			if('s' == op[0])
			{
				in[i] = 0;
				continue;
			}
			scanf("%d%*c", &in[i]);
			if('d' == op[0]) in[i] = -in[i];
			else add[m++] = in[i];
		}
		sort(add,add+m);
		num.clear();
		tol = 0;
		rep(i,0,m)
		{
			if(num.find(add[i]) == num.end())
				num[add[i]] = tol++;
		}
		clc(sum,0);
		clc(cnt,0);
		rep(i,0,q)
		{
			if(!in[i]) printf("%I64d\n",sum[id(0,tol-1)][3]);
			else
			{
				p = num[abs(in[i])], v = in[i];
				update(0,tol-1);
			}
		}
	}
	return 0;
}

 

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

请输入正确的验证码