杭电 HOJ 1166 敌兵布阵 解题报告
直接求超时。用线段树。简单做法直接用2N数组,以1为root,2*i为左节点,2*i+1为右节点。
求区间[a,b]和时,如果a为右节点,则减去左节点的值。如果b为左节点,则减去右节点的值。a,b迭代为自己的父母。当a,b相等时,加上当前节点的值,即为区间和。
我也是第一次接触线段树的概念。刚开始也想自己建立一棵树。在网上找到了张昆玮的线段树的讲稿,才发现可以直接用数组。分享下:http://wenku.baidu.com/view/f27db60ee87101f69e319544.html
#include <iostream> using namespace std; int s[131072]; int main() { char str[10]; int cas,cas2=1; int i,n,t,m,num,sta,end,sum; scanf("%d",&cas); while(cas--) { printf("Case %d:\n",cas2++); scanf("%d",&n); t=n-1; sta=0; while(t) { t>>=1; sta++; } sta=1<<sta; end=sta+n; for(i=sta;i<end;i++) cin>>s[i]; end=sta*2; for(;i<end;i++) s[i]=0; sta--; for(i=sta;i;i--) s[i]=s[t=2*i]+s[t+1]; while(scanf("%s",str) && str[0]!='E') { scanf("%d%d",&m,&num); if(str[0]=='Q') { t=num; sum=0; for(m+=sta,t+=sta;m!=t;t>>=1,m>>=1) { if(m&1) sum-=s[m^1]; if(~t&1) sum-=s[t^1]; } printf("%d\n",sum+s[m]); } else { if(str[0]=='S') num=-num; t=sta+m; while(t) { s[t]+=num; t>>=1; } } } } }
个人感觉代码不是很好看。还有就是不能用cin和cout,会超时。