hdu4288 離線處理線段樹

life4711發表於2015-04-06

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



Problem Description
  In mathematics and computer science, an algorithm describes a set of procedures or instructions that define a procedure. The term has become increasing popular since the advent of cheap and reliable computers. Many companies now employ a single coder to write an algorithm that will replace many other employees. An added benefit to the employer is that the coder will also become redundant once their work is done. 1
  You are now the signle coder, and have been assigned a new task writing code, since your boss would like to replace many other employees (and you when you become redundant once your task is complete).
Your code should be able to complete a task to replace these employees who do nothing all day but eating: make the digest sum.
  By saying “digest sum” we study some properties of data. For the sake of simplicity, our data is a set of integers. Your code should give response to following operations:
  1. add x – add the element x to the set;
  2. del x – remove the element x from the set;
  3. sum – find the digest sum of the set. The digest sum should be understood by

  where the set S is written as {a1, a2, ... , ak} satisfying a1 < a2 < a3 < ... < ak 
  Can you complete this task (and be then fired)?
------------------------------------------------------------------------------
1 See http://uncyclopedia.wikia.com/wiki/Algorithm
 

Input
  There’re several test cases.
  In each test case, the first line contains one integer N ( 1 <= N <= 105 ), the number of operations to process.
  Then following is n lines, each one containing one of three operations: “add x” or “del x” or “sum”.
  You may assume that 1 <= x <= 109.
  Please see the sample for detailed format.
  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.
  Please process until EOF (End Of File).
 

Output
  For each operation “sum” please print one line containing exactly one integer denoting the digest sum of the current set. Print 0 if the set is empty.
 

Sample Input
9 add 1 add 2 add 3 add 4 add 5 sum add 6 del 3 sum 6 add 1 add 3 add 5 add 7 add 9 sum
 

Sample Output
3 4 5
Hint
C++ maybe run faster than G++ in this problem.
/**
hdu4288 離線線段樹
題目大意:對一個起初為空的陣列進行三種操作:add x:插入x:del x:刪除x:sum :查詢在當前數列中下標對5取模為3的數的總和。
解題思路:暴力會超時。可以利用線段樹來做,由於線段樹不支援點的刪除和增加,普通的線上線段樹無法滿足題目要求。我們可以把所有的在輸入中增加過的點全部存上,
          然後去重,組成一個序列,對於其中的元素如果當前線段樹中有,那麼就標記為1,否則為0,維護線段樹中標記的個數cnt,以及對5取模的五種情況的值。
          遇到新增、刪除操作的時候,只要把那個節點的值改變,然後將它對下標的影響處理好就可以。
          那麼如何處理這些操作對下標的影響呢?
          現在我們考慮一個父區間,假設它的左右子區間已經更新完畢。
          顯然,左區間中下標%5的情況與父區間中%5的情況完全相同;
          可是,右區間中卻不一定相同,因為右區間中的下標是以 mid 當作 1 開始的。
          那麼,只要我們知道左區間中有效元素的個數 cnt,我們就能知道右區間中的下標 i 在父區間中對應的下標為 i+cnt。
          所以,雖然我們最終要的只是總區間中下標%5 = 3的和。但是在更新時我們需要知道右區間%5的所有情況。
          於是我們要線上段樹的每個節點開一個 sum[5] 和一個 cnt,分別記錄這個節點中下標%5的5種情況的和與有效元素的個數。
          而查詢時,直接訪問總區間的 sum[3] 即可。
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn=500000+10;

int n,len,flag;
char str[maxn][10];
int num[maxn],s[maxn];

struct node
{
    int l,r,cnt;
    LL sum[5];
}tree[maxn*4];

void init(int l,int r,int i)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].cnt=0;
    memset(tree[i].sum,0,sizeof(tree[i].sum));
    if(l!=r)
    {
        int mid=(l+r)>>1;
        init(l,mid,i<<1);
        init(mid+1,r,2*i+1);
    }
}

void add(int x)
{
    for(int i=0;i<5;i++)
    {
        int j=(i+tree[x<<1].cnt)%5;
        tree[x].sum[j]=tree[x<<1].sum[j]+tree[x<<1|1].sum[i];
    }
}

void insert(int i,int pos,int m)
{
    flag?tree[i].cnt++:tree[i].cnt--;
    if(tree[i].l==tree[i].r)
    {
        tree[i].sum[1]=flag*m;
        return;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    if(pos<=mid)
        insert(i<<1,pos,m);
    else
        insert(i<<1|1,pos,m);
    add(i);
}

int main()
{
    while(~scanf("%d",&n))
    {
        len=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",str[i]);
            if(str[i][0]!='s')
            {
                scanf("%d",&num[i]);
                s[len++]=num[i];
            }
        }
        sort(s,s+len);
        len=unique(s,s+len)-s;
        if(len==0)
        {
            memset(tree[1].sum,0,sizeof(tree[1].sum));
        }
        else
        {
          init(1,len,1);
        }
        for(int i=0;i<n;i++)
        {
            if(str[i][0]=='a')
            {
                flag=1;
                int pos=lower_bound(s,s+len,num[i])-s+1;
                insert(1,pos,num[i]);
            }
            else if(str[i][0]=='d')
            {
                flag=0;
                int pos=lower_bound(s,s+len,num[i])-s+1;
                insert(1,pos,num[i]);
            }
            else
            {
                /*for(int j=0;j<5;j++)
                   printf("%I64d ",tree[1].sum[j]);
                printf("\n");*/
                 printf("%I64d\n",tree[1].sum[3]);
            }
        }
    }
    return 0;
}
/**
18
add 1
add 2
add 3
add 4
add 5
sum
add 6
add 7
add 8
add 9
add 10
add 11
add 12
del 3
add 13
add 14
del 9
sum

answer:14
*/


Problem Description
  In mathematics and computer science, an algorithm describes a set of procedures or instructions that define a procedure. The term has become increasing popular since the advent of cheap and reliable computers. Many companies now employ a single coder to write an algorithm that will replace many other employees. An added benefit to the employer is that the coder will also become redundant once their work is done. 1
  You are now the signle coder, and have been assigned a new task writing code, since your boss would like to replace many other employees (and you when you become redundant once your task is complete).
Your code should be able to complete a task to replace these employees who do nothing all day but eating: make the digest sum.
  By saying “digest sum” we study some properties of data. For the sake of simplicity, our data is a set of integers. Your code should give response to following operations:
  1. add x – add the element x to the set;
  2. del x – remove the element x from the set;
  3. sum – find the digest sum of the set. The digest sum should be understood by

  where the set S is written as {a1, a2, ... , ak} satisfying a1 < a2 < a3 < ... < ak 
  Can you complete this task (and be then fired)?
------------------------------------------------------------------------------
1 See http://uncyclopedia.wikia.com/wiki/Algorithm
 

Input
  There’re several test cases.
  In each test case, the first line contains one integer N ( 1 <= N <= 105 ), the number of operations to process.
  Then following is n lines, each one containing one of three operations: “add x” or “del x” or “sum”.
  You may assume that 1 <= x <= 109.
  Please see the sample for detailed format.
  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.
  Please process until EOF (End Of File).
 

Output
  For each operation “sum” please print one line containing exactly one integer denoting the digest sum of the current set. Print 0 if the set is empty.
 

Sample Input
9 add 1 add 2 add 3 add 4 add 5 sum add 6 del 3 sum 6 add 1 add 3 add 5 add 7 add 9 sum
 

Sample Output
3 4 5
Hint
C++ maybe run faster than G++ in this problem.

相關文章