hdu 3333 Turing Tree

Turing Tree

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1973    Accepted Submission(s): 654


Problem Description
After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again...

Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.
 
Input
The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
 
Output
For each Query, print the sum of distinct values of the specified subsequence in one line.
 
Sample Input
2 3 1 1 4 2 1 2 2 3 5 1 1 2 1 3 3 1 5 2 4 3 5
 
Sample Output
1 5 6 3 6
 
Author
3xian@GDUT
 
Source
 
Recommend
lcy

//这题的做法是先离散化,然后把Q按右边端点进行升序排序

//这是把数据一个个插入、遇到以前出现了的数字,就删除原来的位置的值,在新位置插入

//这样做法的正确性和按Q的右端点排序有关

//遇到坐标和Q右端点相等时就可以完成query,并且保存

//最后按输入小标排序,并输出结果,树状数组比线段树快些

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 33334//我开始把这写成3333,然后后面Q的区间数组有N*3
#define lson l,m,k<<1  //我很二的以为这样已经超过10W了,然后纠结了一下午,
#define rson m+1,r,k<<1|1  //抓狂、、、这题好多3,真被伤到了
using namespace std;
__int64 st[N<<2];
int rc[N],sv[N],rci[N];
bool hash[N];
struct node
{
    int i,j;
    int index;
    __int64 ans;
    bool operator<(const node&a)const
    {
        return j<a.j;
    }
};
node interval[N*3];
int n;
int bf(int &val)
{
   int l=1,r=n,m;
   while(l<=r)
   {
       m=(l+r)>>1;
       if(rc[m]>val) r=m-1;
       else if(rc[m]<val) l=m+1;
       else return m;
   }
}
bool cmp(const node&a,const node&b)
{
    return a.index<b.index;
}
void build(int l,int r,int k)
{
    st[k]=0;
    if(l==r)
     return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void up(int &k)
{
    st[k]=st[k<<1]+st[k<<1|1];
}
int flag;
void update(int index,int l,int r,int k)
{
    if(l==r)
    {
        st[k]=flag;//printf(" flag%.lf  ",flag);
        return;
    }
    int m=(l+r)>>1;
    if(index<=m) update(index,lson);
    else update(index,rson);
    up(k);
}
double query(int &L,int &R,int l,int r,int k)
{
    if(L<=l&&R>=r)
    {
        return st[k];
    }
    int m=(l+r)>>1;
    double t1=0,t2=0;
    if(L<=m) t1=query(L,R,lson);
    if(R>m)  t2=query(L,R,rson);
    return t1+t2;
}
int main()
{
    int T;
    int Q;
    int i,k,rcn;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);rcn=n;
        for(i=1;i<=n;i++)
          scanf("%d",&rc[i]),sv[i]=rc[i],hash[i]=0;
        sort(rc+1,rc+n+1);
        for(k=1,i=2;i<=n;i++)
         if(rc[i]!=rc[k])
          rc[++k]=rc[i];
        n=k;

        scanf("%d",&Q);
        for(i=0;i<Q;i++)
          {
              scanf("%d%d",&interval[i].i,&interval[i].j);
              interval[i].index=i;
          }
        sort(interval,interval+Q);
        //interval[Q].j=-1;

        build(1,rcn,1);
        k=0;int temp;
        for(i=1;i<=rcn;i++)
        {
          temp=bf(sv[i]);
          if(hash[temp])
          {
              flag=0;
              update(rci[temp],1,rcn,1);

              flag=sv[i];
              rci[temp]=i;
              update(i,1,rcn,1);
          }
          else
          {
             hash[temp]=1;

             flag=sv[i];
             rci[temp]=i;
             update(i,1,rcn,1);
          }
          while(i==interval[k].j)
         {
            interval[k].ans=query(interval[k].i,interval[k].j,1,rcn,1);
            k++;
            if(k>=Q) break;
         }
         if(k>=Q) break;
        }
      sort(interval,interval+Q,cmp);
      for(i=0;i<Q;i++)
       printf("%I64d\n",interval[i].ans);
    }
    return 0;
}

//改用树状数组做、快了200Ms吧
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 33334
using namespace std;
struct node
{
    int i,j;
    int index;
    __int64 ans;
    bool operator<(const node&a)const
    {
        return j<a.j;
    }
};
node interval[N*3];
int n,rcn;
__int64 c[N];
int rc[N],sv[N],rci[N];
int lb[N];
bool hash[N];
int bf(int &val)
{
   int l=1,r=n,m;
   while(l<=r)
   {
       m=(l+r)>>1;
       if(rc[m]>val) r=m-1;
       else if(rc[m]<val) l=m+1;
       else return m;
   }
}
bool cmp(const node&a,const node&b)
{
    return a.index<b.index;
}
void update(int index,int val)
{
    for(;index<=rcn;index+=lb[index])
       c[index]+=val;
}
__int64 r_sum(int index)
{
    __int64 sum=0;
    for(;index>0;index-=lb[index])
      sum+=c[index];
    return sum;
}
int main()
{
    int T;
    int Q;
    int i,k;
    for(i=1;i<=30000;i++)lb[i]=i&(-i);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);rcn=n;
        for(i=1;i<=n;i++)
          {
              scanf("%d",&rc[i]);
              sv[i]=rc[i];
              hash[i]=0;
              c[i]=0;
          }
        sort(rc+1,rc+n+1);
        for(k=1,i=2;i<=n;i++)
         if(rc[i]!=rc[k])
          rc[++k]=rc[i];
        n=k;
        scanf("%d",&Q);
        for(i=0;i<Q;i++)
          {
              scanf("%d%d",&interval[i].i,&interval[i].j);
              interval[i].index=i;
          }
        sort(interval,interval+Q);
        k=0;int temp;
        for(i=1;i<=rcn;i++)
        {
          temp=bf(sv[i]);
          if(hash[temp])
          {
              update(rci[temp],-sv[i]);
              rci[temp]=i;
              update(i,sv[i]);
          }
          else
          {
             hash[temp]=1;
             rci[temp]=i;
             update(i,sv[i]);
          }
          while(i==interval[k].j)
         {
        interval[k].ans=r_sum(interval[k].j)-r_sum(interval[k].i-1);
            k++;
            if(k>=Q) break;
         }
         if(k>=Q) break;
        }
       sort(interval,interval+Q,cmp);
      for(i=0;i<Q;i++)
       printf("%I64d\n",interval[i].ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/372465774y/p/2617131.html