hdu4288 Coder(线段树+离散化)

题目链接:

huangjing

题意:

题目中给了三个操作

1:add x 就是把x插进去

2:delete x 就是把x删除

3:sum 就是求下标%5=3的元素的和。

还有一个条件是插入和删除最后都要保证数列有序。。。

首先告诉一种暴力的写法。。因为时间非常充足,需要对stl里面的函数有所了解。。

就是直接申明一个vector的容器,然后直接用vector里面的操作比如 insert,erase等等操作。。不过这个效率很低。。

最后跑出来6000多ms。。(强哥的代码)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<cmath>
#include<string>
#include<queue>
#define eps 1e-9
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

char s[5];
int n;

vector<int>a;

int main()
{
    int len,val;
    vector<int>::iterator iter;
    while(cin>>n)
    {
        len=0;
        a.clear();
        while(n--)
        {
            scanf("%s",s);
            if(s[0]=='s')
            {
                long long ans = 0;
                for(int i=2; i < len ; i+=5)
                    ans += a[i];
                cout<<ans<<endl;
            }
            else if(s[0]=='a')
            {
                len++;
                scanf("%d",&val);
                iter=lower_bound(a.begin(),a.end(),val);
                a.insert(iter,val);
            }
            else
            {
                 len--;
                 scanf("%d",&val);
                 iter= lower_bound(a.begin(),a.end(),val);
                 a.erase(iter); // basic coding
            }
        }
    }
    return 0;
}

第二种方法是线段树做法,这个要维护5颗线段树,结构体里面保存每个节点的个数,首先因为线段树不支持插入,删除,要维护一个个数cnt,当插入一个数的时候,你看原来%3的数,现在取余肯定等于2,那么怎么办呢??那么这个cnt就起到了神奇的作用,每当插入删除的时候就把相应的节点数变化,来维护那5棵线段树。。最后因为没有告诉数据范围,所以要采取离散化,然后离线处理,最后得出所有要操作的总个数,然后依此建树,第一次用离散化,觉得好高大上。。。

代码:(参考自cxlove)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<cmath>
#include<string>
#include<queue>
#define eps 1e-9
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=100000+10;
int n,a[maxn],b[maxn];
char op[maxn][5];

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

void buildtree(int l,int r,int dex)
{
    tree[dex].cnt=0;
    memset(tree[dex].sum,0,sizeof(tree[dex].sum));
    if(l==r)  return;
    int mid=(l+r)>>1;
    buildtree(l,mid,dex<<1);
    buildtree(mid+1,r,dex<<1|1);
}

void push_up(int dex)
{
    for(int i=0;i<5;i++)
        tree[dex].sum[i]=tree[dex<<1].sum[i]+tree[dex<<1|1].sum[((i-tree[dex<<1].cnt)%5+5)%5];
}

void update(int l,int r,int dex,int pos,int flag,int val)
{
    tree[dex].cnt+=flag;
    if(l==r)
    {
        if(flag==1)
           tree[dex].sum[1]=val;
        else
           tree[dex].sum[1]=0;
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)  update(l,mid,dex<<1,pos,flag,val);
    else update(mid+1,r,dex<<1|1,pos,flag,val);
    push_up(dex);
}

int main()
{
    int tot,pos,flag;
    while(~scanf("%d",&n))
    {
        tot=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",op[i]);
            if(op[i][0]!='s')
            {
                scanf("%d",&b[i]);
                a[tot++]=b[i];
            }
        }
        sort(a,a+tot);
        tot=unique(a,a+tot)-a;
        if(tot==0)  memset(tree[1].sum,0,sizeof(tree[1].sum));
        else buildtree(1,tot,1);
        for(int i=1;i<=n;i++)
        {
            pos=lower_bound(a,a+tot,b[i])-a;
            pos++;
            if(op[i][0]=='a')
            {
                flag=1;
                update(1,tot,1,pos,flag,b[i]);
            }
            else if(op[i][0]=='d')
            {
                flag=-1;
                update(1,tot,1,pos,flag,b[i]);
            }
            else
                printf("%I64d\n",tree[1].sum[3]);
        }
    }
    return 0;
}

时间: 2024-08-24 11:15:05

hdu4288 Coder(线段树+离散化)的相关文章

HDU4288 Coder(线段树)

注意添加到集合中的数是升序的,先将数据读入,再离散化. sum[rt][i]表示此节点的区域位置对5取模为i的数的和,删除一个数则右边的数循环左移一位,添加一个数则右边数循环右移一位,相当于循环左移4位,线段树与树状数组结合,树状数组确定位置. le[rt]表示左移的位数,区间更新懒惰标记 #include <iostream> #include <cstdio> #include<cstdlib> #include<map> #include<alg

POJ_2528 Mayor&#39;s poster(线段树+离散化)

题目请点我 题解: 这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷.把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变. 举个例子: 区间:[2,6],[4,8],[6,10] 我们进行下面对应: 2 4 6 8 10 1 2 3 4 5 则原区间变为[1,3],[2,4],[3,5].可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

HDU5124:lines(线段树+离散化)或(离散化思想)

http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which is covered by the most lines. John wants to know how many lines cover A. Input The first line conta

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

hdu 5124 lines (线段树+离散化)

lines Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 620    Accepted Submission(s): 288 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which

poj2528 线段树+离散化

1 //Accepted 1960K 110MS 2 //线段树+离散化 3 //把所有的坐标排序,从小到大编号,建立线段树 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 /** 1

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj2528--Mayor&#39;s posters(线段树+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41785   Accepted: 12164 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post