hdu 4288 Coder (线段树+离线)

题意:

刚开始有一个空集合。有三种操作:

1.往集合中加入一个集合中不存在的数 x

2.从集合中删除一个已经存在的数 x

3.计算集合的digest sum并输出。       digest sum求法:将集合中所有数从小到大排序,得到a1<a2<...<an。 digest sum = sum(ai) where i mod 5 = 3

数据范围:

N ( 1 <= N <= 105 )

1 <= x <= 109.

For any “add x” it is guaranteed that x is not currently in the set just before this operation.
For any “del x” it is guaranteed that x must currently be in the set just before this operation.

思路:

先将所有增加过的,删除过的数存下来,去重,搞成线段树。

每个结点(区间)里有两个东西,一个是 cnt,记录该区间的在集合中的元素的个数。一个是sum[i] , sum[i]:该区间序号%5等于i的存在于集合中的元素的总和。

插入和删除时维护即可。

代码:

int const maxn=1e5+5;

struct node{
    int cnt;
    ll sum[5];
}tree[maxn<<2];

int n,tot;
int q[maxn],a[maxn];
char ope[maxn][15];

void build(int l,int r,int rt){
    tree[rt].cnt=0;
    memset(tree[rt].sum,0,sizeof(tree[rt].sum));
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void pushUp(int rt){
    rep(i,0,4)
        tree[rt].sum[i]=tree[rt<<1].sum[i]+tree[rt<<1|1].sum[((5-tree[rt<<1].cnt%5)%5+i)%5];
}
void update(int k,int pos,int num,int l,int r,int rt){
    tree[rt].cnt+=k;
    if(l==r){
        tree[rt].sum[0]+=(k*num);
        return;
    }
    int m=(l+r)>>1;
    if(pos<=m)
        update(k,pos,num,lson);
    else
        update(k,pos,num,rson);
    pushUp(rt);
}

int main(){
    //freopen("test.in","r", stdin);
    while(scanf("%d",&n)!=EOF){
        tot=0;
        rep(i,1,n){
            scanf("%s",ope[i]);
            if(ope[i][0]!=‘s‘){
                scanf("%d",&q[i]);
                a[tot++]=q[i];
            }
        }
        sort(a,a+tot);
        tot=unique(a,a+tot)-a;
        if(tot==0)
            memset(tree[1].sum,0,sizeof(tree[1].sum));
        else
            build(1,tot,1);
        rep(i,1,n){
            int pos=lower_bound(a,a+tot,q[i])-a+1;
            if(ope[i][0]==‘a‘){
                update(1,pos,q[i],1,tot,1);
                continue;
            }
            if(ope[i][0]==‘d‘){
                update(-1,pos,q[i],1,tot,1);
                continue;
            }
            printf("%I64d\n",tree[1].sum[2]);
        }
    }
    //fclose(stdin);
}
时间: 2024-10-16 09:59:37

hdu 4288 Coder (线段树+离线)的相关文章

HDU 4638-Group(线段树+离线处理)

题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号,要考虑和他相邻的标号的位置,若前面位置出现了和它相邻的标号, 则前面位置组数减一(因为可以合并成一组),查询区间离线处理,保证了查询的正确. #include <map> #include <set> #include <list> #include <cmath&g

HDU - 3874 Necklace (线段树 + 离线处理)

欢迎参加--每周六晚的BestCoder(有米!) Necklace Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4003    Accepted Submission(s): 1330 Problem Description Mery has a beautiful necklace. The necklace is made

gcd(线段树离线处理)——HDU 4630

对应HDU题目:点击打开链接 No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1801    Accepted Submission(s): 770 Problem Description Life is a game,and you lose it,so you suicide. But you can

Necklace HDU - 3874 (线段树/树状数组 + 离线处理)

Necklace HDU - 3874 Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

Super Mario(线段树离线区间k值)

以前见过这题,没做出来,知道是离线处理,这次仔细想了下, 首先把出现的高度都map离散化一下,以离散化出来的数目g建树,把每个位置都开俩个vector,一个存以这个位置为L的询问,一个存以这个位置为R的询问. 然后从1-g 进行更新,假如当前i是以第j个区间的开始位置,那么这时就可以询问一下<=p[j].h的个数s,显然这时第J个区间多加的,需要减掉,p[j].sum-=s; 然后更新第i个数,update(a[i],1,g,1);再找到某第k区间是以i结尾的,那么依旧询问一下,得出s,p[k]

hdu 4288 Coder

http://acm.hdu.edu.cn/showproblem.php?pid=4288 题意:add 就是在集合里面加上一个数x: del 就是从集合里删去一个数x: sum是求位置i%5==3的数的和. tree[i].sum[5] 里面数组存的是不同位置%5之后分别对应的和. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100010 5 using

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek