hdu1166
尼玛,无力吐槽,搞了几个小时,没想到是输出Case 时出错
这种类型是线段树,关于线段树,线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。参照这个图理解下

建树:
void build(int left,int right,int i)
{
int mid;
b[i].left=left;
b[i].right=right;
if(left==right)
{
b[i].sum=a[left];
return ;
}
mid=(left+right)/2;
build(left,mid,2*i);
build(mid+1,right,2*i+1);
b[i].sum=b[2*i].sum+b[2*i+1].sum;
}
查找:
int Query(int left, int right,int i)
{
int mid;
if(b[i].left==left && b[i].right ==right) return b[i].sum;
mid=(b[i].left+b[i].right)/2;
if(right<=mid) return Query(left,right,2*i);
else if (left>mid ) return Query(left,right,2*i+1);
else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1);
}
删除,增加:
void Add(int id,int num,int i)
{
if(b[i].left==b[i].right)
{
b[i].sum=b[i].sum+num;
return ;
}
else
{
b[i].sum=b[i].sum+num;
if(id<=b[i*2].right) Add(id,num,2*i);
else Add(id,num,2*i+1);
}
}
所以,有了以上函数,这道题就不会超时了啊
#include <stdio.h>
#include <string.h>
int a[50010];
struct node
{
int left,right,sum;
}b[150010];
void build(int left,int right,int i)
{
int mid;
b[i].left=left;
b[i].right=right;
if(left==right)
{
b[i].sum=a[left];
return ;
}
mid=(left+right)/2;
build(left,mid,2*i);
build(mid+1,right,2*i+1);
b[i].sum=b[2*i].sum+b[2*i+1].sum;
}
void Add(int id,int num,int i)
{
if(b[i].left==b[i].right)
{
b[i].sum=b[i].sum+num;
return ;
}
else
{
b[i].sum=b[i].sum+num;
if(id<=b[i*2].right) Add(id,num,2*i);
else Add(id,num,2*i+1);
}
}
int Query(int left, int right,int i)
{
int mid;
if(b[i].left==left && b[i].right ==right) return b[i].sum;
mid=(b[i].left+b[i].right)/2;
if(right<=mid) return Query(left,right,2*i);
else if (left>mid ) return Query(left,right,2*i+1);
else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1);
}
int main()
{
int Case;
int n;
char str[10];
scanf("%d",&Case);
int id,num;
int i;
int k=1;
while(Case--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,n,1);
printf("Case %d:\n",k++);
while(1)
{
scanf("%s",str);
if(strcmp(str,"End")==0) break;
scanf("%d%d",&id,&num);
if(strcmp(str,"Query")==0)
{
printf("%d\n",Query(id,num,1));
}
if(strcmp(str,"Add")==0)
{
//scanf("%d%d",&id,&num);
Add(id,num,1);
}
if(strcmp(str,"Sub")==0)
{
//scanf("%d%d",&id,&num);
Add(id,-num,1);
}
}
}
return 0;
}
浙公网安备 33010602011771号