离散+离线+线段树。。。题目不是自己做的,自己做不来。。百度的题解。。大致讲下解题思路。
把数据全读进来,离线处理。处理询问:按询问的右端点对所有询问排序。处理点:点的个数有30000个,但是点的大小可以达到1e9,很容易想到用离散来处理,这样就可以开30000的数组保存当前存在的点的下标。。把点按原来读进来的顺序再排回去,挨个处理点。如果之前这个数有了,把前面的数删了,再把这个数加到线段树里面,这样就能保证线段树里面的数都是最靠近当前询问的右端。。这样就可以了。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 30005 #define eps 1e-6 #define mod 1000000007 #define INF 99999999 #define lowbit(x) (x&(-x)) #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; struct qu { int x, y; LL res; int number; }q[100005]; struct node { int number; int h, v; }tmp[maxn]; int hash[maxn]; LL sum[maxn<<2]; int n, m, k; int value, p; int ql, qr; LL ans; void read(void) { int i; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d", &tmp[i].v); tmp[i].number=i; } scanf("%d", &m); for(i=1;i<=m;i++){ scanf("%d%d", &q[i].x, &q[i].y); q[i].number=i; } } int cmp1(node a, node b) { return a.v<b.v; } int cmp2(node a, node b) { return a.number<b.number; } int cmp3(qu a, qu b) { return a.y<b.y; } int cmp4(qu a, qu b) { return a.number<b.number; } void work(void) { sort(tmp+1, tmp+n+1, cmp1); int temp=0, i; tmp[1].h=++temp; for(i=2;i<=n;i++) if(tmp[i].v==tmp[i-1].v) tmp[i].h=temp; else tmp[i].h=++temp; sort(tmp+1, tmp+n+1, cmp2); sort(q+1, q+m+1, cmp3); } void pushup(int o) { sum[o]=sum[o<<1]+sum[o<<1 | 1]; } void updata(int o, int L, int R) { if(L==R){ if(k) sum[o]=0; else sum[o]=value; return; } int mid=(R+L)>>1; if(p<=mid) updata(lson); else updata(rson); pushup(o); } void query(int o, int L, int R) { if(ql<=L && qr>=R){ ans+=sum[o]; return; } int mid=(R+L)>>1; if(ql<=mid) query(lson); if(qr>mid) query(rson); } void solve(void) { memset(hash, 0, sizeof hash); memset(sum, 0, sizeof sum); int i, j; for(i=1, j=1;i<=n;i++){ if(hash[tmp[i].h]){ p=hash[tmp[i].h], k=1, value=tmp[hash[tmp[i].h]].v; updata(1, 1, n); } p=i, k=0, value=tmp[i].v; hash[tmp[i].h]=i; updata(1, 1, n); while(j<=m && q[j].y<=i){ ql=q[j].x, qr=q[j].y, ans=0; query(1, 1, n); q[j++].res=ans; } } sort(q+1, q+m+1, cmp4); for(i=1;i<=m;i++) printf("%I64d\n", q[i].res); } int main(void) { int _; while(scanf("%d",&_)!=EOF){ while(_--){ read(); work(); solve(); } } return 0; }