神思維線段樹
題目大意:給一串數字。然後給一切區間。
給你區間的時候 要求區間內相同的數字只算一次,然後求和。
思路:
我們把詢問的Q個區間 按照右端點排序。然後我們按照順序插入的時候。
用pre 數組 記錄下出現他前一個的位置。如果為零就代表沒有出現過。
如果有的話 ,就把那個地方刪除掉。沒有就插入。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define lson num<<1,s,mid#define rson num<<1|1,mid+1,e#define maxn 30005typedef __int64 LL;using namespace std;LL tree[maxn<<2]; //樹上的節點LL X[maxn]; //給的數字序列int pre[maxn];//pre 數組 如上LL ans[maxn<<2];//排序之後順序亂了 記錄ansLL C[maxn];//離散化數組int n,k;struct node{ int s,e; int id; bool operator < (const node &cmp) const{ return e<cmp.e; }}Q[maxn<<2];int bin(int tag) //離散化的二分{ int bot=1,top=k-1; int mid; while(top>=bot) { mid=(top+bot)>>1; if(C[mid]>tag)top=mid-1; else if(C[mid]<tag)bot=mid+1; else return mid; } return 0;}void debug(int num,int s,int e) //debug函數 debug神器 【壞笑】{ if(s==e) { printf("%d ",tree[num]); return ; } int mid=(s+e)>>1; debug(lson); debug(rson);}void pushup(int num){ tree[num]=tree[num<<1]+tree[num<<1|1];}void build(int num,int s,int e){ tree[num]=0; if(s==e)return; int mid=(s+e)>>1; build(lson); build(rson);}void update(int num,int s,int e,int pos,int val){ if(s==e) { tree[num]=val; return; } int mid=(s+e)>>1; if(pos<=mid)update(lson,pos,val); else update(rson,pos,val); pushup(num);}LL query(int num,int s,int e,int l,int r){ int mid=(s+e)>>1; if(s==l && e==r) { return tree[num]; } if(r<=mid)return query(lson,l,r); else if(l>mid)return query(rson,l,r); else return query(lson,l,mid)+query(rson,mid+1,r);}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%I64d",&X[i]); C[i]=X[i]; } sort(C+1,C+n+1); k=2; for(int i=2;i<=n;i++) { if(C[i]!=C[i-1])C[k++]=C[i]; //離散化 } int op; scanf("%d",&op); for(int i=1;i<=op;i++) { scanf("%d%d",&Q[i].s,&Q[i].e); Q[i].id=i; } sort(Q+1,Q+op+1); memset(pre,0,sizeof(pre)); int tmp=1; int pos=1; while(tmp<=op) { // printf("X[pos]=%d\n",X[pos]); int index=bin(X[pos]); if(pre[index]==0) { update(1,1,n,pos,X[pos]); pre[index]=pos; } else { update(1,1,n,pre[index],0); update(1,1,n,pos,X[pos]); pre[index]=pos; } //printf("pos=%d,Q[tmp].e=%d\n",pos,Q[tmp].e); while(pos==Q[tmp].e)//因為可能出現很多相同的右端點,用while { ans[Q[tmp].id]=query(1,1,n,Q[tmp].s,Q[tmp].e); tmp++; //debug(1,1,n); // cout<<endl; } pos++; } for(int i=1;i<=op;i++) printf("%I64d\n",ans[i]); //被I64坑了。。。 } return 0;}