hdu 3333 Turing Tree(线段树+离散化)
刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望。
刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的。
前两天我在做一道题的时候,也是因为数据范围太大(同样是1000000000)不能打表,当时想了许久,想到把这些数值存进一个数组里面,对这个数组进行排序,然后对于其中的某个值可以进行二分查找。今天我又长姿势了,原来这种方法叫做离散化。
刚开始我想着可以把那些相同的值用0去替代,但是一个解决不了的问题是如果把两个相同的值其中一个改为0,那么如果问题区间刚好包含这个值不包含另一个值该怎么处理,甚至如果问题区间问的就是这个值,那该怎么办。
苦思良久也没想到什么好办法。看了下别人的思路,是将所有的问题区间放在一起,以区间的右边界为关键字进行排序,然后对于线段树的值边插入边更新,具体思路见代码。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define N 100005 #define M 30005 struct node { int x,y; int id; }Q[N]; struct tree { int x,y; __int64 sum; }a[M*3]; int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; } int cmp1(const void *a,const void *b) { node *c; node *d; c=(node *)a; d=(node *)b; return c->y-d->y; } int visit[M],temp[M],tem[M],b[M]; __int64 ans[N]; void CreatTree(int t,int x,int y) { a[t].x=x; a[t].y=y; a[t].sum=0; if(x==y) return ; int temp=t*2; int mid=(x+y)/2; CreatTree(temp,x,mid); CreatTree(temp+1,mid+1,y); return ; } void InsertTree(int t,int x,int y) { if(a[t].x==a[t].y) { a[t].sum+=y; return ; } int temp=t*2; int mid=(a[t].x+a[t].y)/2; if(x<=mid) InsertTree(temp,x,y); else InsertTree(temp+1,x,y); a[t].sum=a[temp].sum+a[temp+1].sum; return ; } __int64 FindTree(int t,int x,int y) { if(a[t].x==x&&a[t].y==y) return a[t].sum; int temp=t*2; int mid=(a[t].x+a[t].y)/2; __int64 sum; sum=0; if(y<=mid) sum+=FindTree(temp,x,y); else if(x>mid) sum+=FindTree(temp+1,x,y); else { sum+=FindTree(temp,x,mid); sum+=FindTree(temp+1,mid+1,y); } return sum; } int Find(int x,int k) { int l,r,mid; l=1; r=k; while(l<=r) { mid=(l+r)/2; if(temp[mid]>x) r=mid-1; else if(temp[mid]<x) l=mid+1; else return mid; } return 0; } int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); CreatTree(1,1,n); int i,j,k; j=0; for(i=1;i<=n;i++) { scanf("%d",&b[i]); tem[j++]=b[i]; } qsort(tem,j,sizeof(tem[0]),cmp); k=0; temp[0]=tem[0]; for(i=1;i<j;i++) { if(tem[i]!=temp[k]) { k++; temp[k]=tem[i]; } } memset(visit,0,sizeof(visit)); int m; scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&Q[i].x,&Q[i].y); Q[i].id=i; } qsort(Q+1,m,sizeof(Q[0]),cmp1); j=1; for(i=1;i<=n;i++) { int flag; int id; id=Find(b[i],k); flag=visit[id]; if(flag) InsertTree(1,flag,-b[i]); InsertTree(1,i,b[i]); visit[id]=i; for(;j<=m;j++) { if(i==Q[j].y) { __int64 tt; tt=FindTree(1,Q[j].x,Q[j].y); ans[Q[j].id]=tt; } else break; } } for(i=1;i<=m;i++) printf("%I64d\n",ans[i]); } return 0; }