HDU 3333--Turing Tree (线段树+离线询问处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3333

题目大意:有n个数,m次询问,每次询问$[l,r]$中不同数的和

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

emmmm,看到这题。。。很明显我们可以对询问按照$r$小优先排序,然后我们将每个数丢到线段树的时候看看这个数是否出现过,如果出现过了,那么很明显,坐标越大的越优(如果$l$能够覆盖小坐标,那么一定能够覆盖大坐标),所以我们直接删除掉上一个位置的值,然后在新的位置更新该值。至于查看,我们可以用unordered_map来记录一下。

还有就是cin,cout即使关了同步。。。也好慢的说QAQ。。。cout中用来endl跑了2500+ms,用'\n'代替endl跑了1500+ms,用scanf,printf跑了500+ms

以下是AC代码:

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <unordered_map>
using namespace std;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lc rt<<1
#define rc rt<<1|1
typedef long long ll;
const int mac=3e4+10;
const int maxn=1e5+10;

struct node
{
    int l,r,id;
    bool operator<(const node&a)const{
        return r<a.r;
    }
}qs[maxn];
ll tree[mac<<2],ans[maxn];
int a[mac];

void update(int l,int r,int rt,int pos,int val)
{
    if (l==r) {tree[rt]+=val; return;}
    int mid=(l+r)>>1;
    if (mid>=pos) update(lson,pos,val);
    else {update(rson,pos,val);}
    tree[rt]=tree[lc]+tree[rc];
}

ll query(int l,int r,int rt,int L,int R)
{
    ll ans=0;
    if (l>=L && r<=R) return tree[rt];
    int mid=(l+r)>>1;
    if (mid>=L) ans+=query(lson,L,R);
    if (mid<R) ans+=query(rson,L,R);
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        int n,m;
        cin>>n;
        for (int i=1; i<=n; i++)
            cin>>a[i];
        cin>>m;
        for (int i=1; i<=m; i++){
            int l,r;
            cin>>l>>r;
            qs[i]=node{l,r,i};
        }
        sort(qs+1,qs+1+m);
        memset(tree,0,sizeof tree);
        unordered_map<int,int>q;
        int st=1;
        for (int i=1; i<=m; i++){
            while (qs[i].r>=st){
                if (q[a[st]]) update(1,n,1,q[a[st]],-a[st]);
                update(1,n,1,st,a[st]);
                q[a[st]]=st;
                st++;
            }
            ans[qs[i].id]=query(1,n,1,qs[i].l,qs[i].r);
        }
        for (int i=1; i<=m; i++)
            cout<<ans[i]<<'\n';
    }
    return 0;
}
posted @ 2020-07-09 16:24  lonely_wind  阅读(190)  评论(0编辑  收藏  举报