题意:n个数 m个询问
询问的是[l, r]区间内不同的数的和
没有修改,静态的主席树即可
与 SPOJ QUERY 一样 将重复的元素建树即可
注意范围:$N \le 50000$ 每个值不超过1000000
也就是加起来会爆int 要用LL
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 #define lson l, m 5 #define rson m+1, r 6 const int N=5e4+5; 7 8 int L[N<<5], R[N<<5]; 9 LL sum[N<<5]; 10 int tot; 11 int a[N], T[N]; 12 int read() 13 { 14 char ch=‘ ‘; 15 int ans=0; 16 while(ch<‘0‘ || ch>‘9‘) 17 ch=getchar(); 18 while(ch<=‘9‘ && ch>=‘0‘) 19 { 20 ans=ans*10+ch-‘0‘; 21 ch=getchar(); 22 } 23 return ans; 24 } 25 26 int build(int l, int r) 27 { 28 int rt=(++tot); 29 sum[rt]=0; 30 if(l<r) 31 { 32 int m=(l+r)>>1; 33 L[rt]=build(lson); 34 R[rt]=build(rson); 35 } 36 return rt; 37 } 38 39 int update(int pre, int l, int r, int x, int val) 40 { 41 int rt=(++tot); 42 L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+val; 43 if(l<r) 44 { 45 int m=(l+r)>>1; 46 if(x<=m) 47 L[rt]=update(L[pre], lson, x, val); 48 else 49 R[rt]=update(R[pre], rson, x, val); 50 } 51 return rt; 52 } 53 54 LL query(int u, int v, int l, int r, int k) 55 { 56 if(l>=k) 57 return sum[v]-sum[u]; 58 int m=(l+r)>>1; 59 LL ans=0; 60 if(m>=k) 61 ans+=query(L[u], L[v], lson, k); 62 ans+=query(R[u], R[v], rson, k); 63 return ans; 64 } 65 66 LL all[N]; 67 int main() 68 { 69 int t; 70 scanf("%d", &t); 71 while(t--) 72 { 73 tot=0; 74 int n=read(); 75 // scanf("%d", &n); 76 all[0]=0; 77 for(int i=1; i<=n; i++) 78 { 79 // scanf("%d", &a[i]); 80 a[i]=read(); 81 all[i]=all[i-1]+a[i]; 82 } 83 T[0]=0; 84 map<int, int> mp; 85 mp.clear(); 86 for(int i=1; i<=n; i++) 87 { 88 if(mp.find(a[i])!=mp.end()) 89 T[i]=update(T[i-1], 1, n, mp[a[i]], a[i]); 90 else 91 T[i]=T[i-1]; 92 mp[a[i]]=i; 93 } 94 int m=read(); 95 // scanf("%d", &m); 96 while(m--) 97 { 98 int l, r; 99 l=read(), r=read(); 100 // scanf("%d%d", &l, &r); 101 printf("%I64d\n", all[r]-all[l-1]-query(T[l-1], T[r], 1, n, l)); 102 } 103 } 104 return 0; 105 }
HDOJ 3874
时间: 2024-10-13 00:15:30