http://acm.hdu.edu.cn/showproblem.php?pid=4288

開始的时候,果断TLE,做的方法是,线段树上只维护%5==3的坐标,比方1 2 3 4 5 6 7  假设删除第三个数,就将3,6的位置全+1,就是向右偏移以为,可是求和还是非常慢,所以即使10秒,还是TLE。。。

正确做法:

1、节点内维护sum[0...4]分别代表区间内%5==i的和

2、结点维护点的个数,cnt

3、离散化处理,然后每次插入时,经过的结点cnt+1或-1,叶子节点Sum[0]就是节点值,父节点的sum这样维护了:非常不错的方法

void pushup(int rt)
{
for(int i=0;i<5;i++)
nodes[rt].sum[i]=nodes[ls(rt)].sum[i]+nodes[rs(rt)].sum[ ((i-nodes[ls(rt)].cnt)%5+5)%5 ];
}

4、离散化+离线,能够使删除数比較方便,不用map

新学会的离散化方法:

for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
tmp[num++]=a[i];
}
sort(tmp,tmp+num);
num=unique(tmp,tmp+num)-tmp;
//然后能够这样查询位置
int pos=lower_bound(tmp,tmp+num,a[i])-tmp;

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
#define IN(s) freopen(s,"r",stdin)
#define CL(a,b) memset(a,b,sizeof(a))
#define ll long long
#define ls(rt) rt*2
#define rs(rt) rt*2+1
const int MAXN = 1e5+100; struct Node{
int l,r;
ll sum[5]; //
int cnt; //区间内数的个数
}nodes[MAXN*4]; int a[MAXN],n,tmp[MAXN];
char op[MAXN][6]; void build(int rt,int l,int r)
{
nodes[rt].l=l;
nodes[rt].r=r;
nodes[rt].cnt=0;
CL(nodes[rt].sum,0);
if(l==r)return;
int mid=(l+r)/2;
build(ls(rt),l,mid);
build(rs(rt),mid+1,r);
} void pushup(int rt)
{
for(int i=0;i<5;i++)
nodes[rt].sum[i]=nodes[ls(rt)].sum[i]+nodes[rs(rt)].sum[ ((i-nodes[ls(rt)].cnt)%5+5)%5 ];
} void update(int rt, int pos, int d, int flag)
{
nodes[rt].cnt+=flag;
if(nodes[rt].l == nodes[rt].r)
{
nodes[rt].sum[0]+=d;
return;
}
if(pos<=nodes[ls(rt)].r)update(ls(rt),pos,d,flag);
else update(rs(rt),pos,d,flag);
pushup(rt);
} int main()
{
//IN("hdu4288.txt");
int num;
while(~scanf("%d",&n))
{
num=0;
for(int i=0;i<n;i++)
{
scanf("%s",op[i]);
if(op[i][0]!='s')
{
scanf("%d",&a[i]);
tmp[num++]=a[i];
}
}
sort(tmp,tmp+num);
num=unique(tmp,tmp+num)-tmp;
build(1,1,num);
for(int i=0;i<n;i++)
{
int pos=lower_bound(tmp,tmp+num,a[i])-tmp;
if(op[i][0] == 'a')update(1,pos,a[i],1);
if(op[i][0] == 'd')update(1,pos,-a[i],-1);
if(op[i][0] == 's')printf("%I64d\n",nodes[1].sum[2]);
}
}
return 0;
}

hdu 4288 线段树+离线+离散化的更多相关文章

  1. 玲珑oj 1117 线段树+离线+离散化,laz大法

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

  2. hdu 4288 线段树 暴力 **

    题意: 维护一个有序数列{An},有三种操作: 1.添加一个元素. 2.删除一个元素. 3.求数列中下标%5 = 3的值的和. 解题思路: 看的各种题解,今天终于弄懂了. 由于线段树中不支持添加.删除 ...

  3. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  4. HDU 3607 线段树+DP+离散化

    题意:从左往右跳箱子,每个箱子有金币数量,只能从矮处向高处跳,求最大可获得金币数,数据规模1<=n<=1e5. 显然是一个dp的问题,不难得出dp[ i ] = max(dp[j] )+v ...

  5. J - Super Mario HDU - 4417 线段树 离线处理 区间排序

    J - Super Mario HDU - 4417 这个题目我开始直接暴力,然后就超时了,不知道该怎么做,直接看了题解,这个习惯其实不太好. 不过网上的思路真的很厉害,看完之后有点伤心,感觉自己应该 ...

  6. HDU 4288 线段树+离散化

    题意: n个操作 在[1, 100000]  的区间上add 或del数( 必不会重复添加或删除不存在的数) sum 求出整个集合中 (下标%5 == 3 位置) 的数   的和 注意数据类型要64位 ...

  7. 覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积

    #include<cstdio> #include<map> #include<algorithm> using namespace std; ; struct N ...

  8. HDU 1542 线段树+扫描线+离散化

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  9. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

随机推荐

  1. 洛谷 P1414 又是毕业季II (多个数的最大公因数)

    这道题其实不难,但是我想复杂了 我想的是把每个数质因数分解,然后每次就枚举每个质因数 来求最小公倍数. 然后想了想这样复杂度将会非常的大,肯定超时 然后看了题解发现不需要质因数分解,直接存因数的个数就 ...

  2. tp框架 验证码的应用注意事项

    1如何点击更换二维码 二维码是img标签的src访问生成二维码的方法.绑定点击事件,ajax的get方式请求生成二维码的函数.在U函数后面加上任意不重复的参数 如  ?rand=’+math.rand ...

  3. C#-逆变 协变 反射 代码

    首先看一段测试代码,自己写的 class Program { static void Main(string[] args) { man OneMan = new man(); var d = One ...

  4. POJ 3744

    矩阵快速乘求概率,不难.但有注意的一点是,一定要注意地雷连着的情况,一旦出现两个雷相邻,就必定为0了. #include <iostream> #include <algorithm ...

  5. intellij idea 打开两个 terminal

    intellij idea 打开两个  terminal alt+f12可以打开terminal,在terminal窗口左侧点击绿色的加号,就可以又打开一个terminal,用tab标签展示:

  6. hdu5389(DP)

    题意: 给出n个人的id,有两个门,每一个门有一个标号.我们记作a和b,如今我们要将n个人分成两组,进入两个门中,使得两部分人的标号的和(迭代的求,直至变成一位数.我们姑且叫做求"和&quo ...

  7. C++ OTL MySQL(Windows/Linux) V8.1

    Windows每秒钟10000条以上插入:Linux每秒插入300条以上.Q269752451 输出截图: Linux输出: Windows输出: 有须要的联系 QQ 3508551694 water ...

  8. 外网主机如何将数据包发送到共用一个公网IP的局域网某特定主机上的

    内网的一台电脑要上因特网对外开放服务或接收数据.都须要port映射.port映射分为动态和静态. 动态port映射:内网中的一台电脑要訪问站点.会向NAT网关发送数据包.包头中包含对方站点IP.por ...

  9. 小记 SqlHelper

    using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;u ...

  10. 黑马day14 过滤器概述&amp;生命周期&amp;运行过程

    过滤器:当訪问一个web资源的时候,过滤器就在你訪问这个web资源的前进行拦截...在放行过后...filter过滤器也能够做一些其它的事情. 编写过滤器的步骤: 1.写一个过滤器类实现filter接 ...