HDU 3874 Necklace(离线算法+树状数组)
离线算法,以前做过一个,非常神奇。
先把所有的区间,按Y排序,再按X排,然后算每一个区间,如果遇到了相同的就把前一个点更新一下-num[le],当前点插入。如果相同直接插入。再区间求和,记录结果。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 #define N 200001 7 #define LL __int64 8 struct node 9 { 10 int x,y,id; 11 }que[N]; 12 int hash[1000001]; 13 int n; 14 LL p[50001]; 15 int num[50001]; 16 LL output[N]; 17 void CL() 18 { 19 memset(p,0,sizeof(p)); 20 memset(hash,0,sizeof(hash)); 21 } 22 int cmp(node a,node b) 23 { 24 if(a.y == b.y) 25 return a.x < b.x; 26 else 27 return a.y < b.y; 28 } 29 int lowbit(int t) 30 { 31 return t&(-t); 32 } 33 void insert(int t,int d) 34 { 35 while(t <= n) 36 { 37 p[t] += d; 38 t += lowbit(t); 39 } 40 } 41 LL getsum(int t) 42 { 43 LL sum = 0; 44 if(t == 0) return 0; 45 while(t > 0) 46 { 47 sum += p[t]; 48 t -= lowbit(t); 49 } 50 return sum; 51 } 52 int main() 53 { 54 int i,cas,m,le; 55 scanf("%d",&cas); 56 while(cas--) 57 { 58 CL(); 59 scanf("%d",&n); 60 for(i = 1;i <= n;i ++) 61 scanf("%d",&num[i]); 62 scanf("%d",&m); 63 for(i = 1;i <= m;i ++) 64 { 65 scanf("%d%d",&que[i].x,&que[i].y); 66 que[i].id = i; 67 } 68 sort(que+1,que+m+1,cmp); 69 le = 1; 70 for(i = 1;i <= m;i ++) 71 { 72 while(le <= que[i].y) 73 { 74 if(hash[num[le]]) 75 { 76 insert(hash[num[le]],-num[le]); 77 } 78 hash[num[le]] = le; 79 insert(le,num[le]); 80 le ++; 81 } 82 output[que[i].id] = getsum(que[i].y) - getsum(que[i].x-1); 83 } 84 for(i = 1;i <= m;i ++) 85 printf("%I64d\n",output[i]); 86 } 87 return 0; 88 }