暑假集训之后写的第一篇博客。。
开学以来一直在准备网络赛,前几场比赛的还可以,再有10天就现场赛了,感觉时间过的好快,好像还有好多的东西都没接触
呢。 哎,学校条件不够优越,马上要比赛了还要天天上课。 今年尽力吧,争取拿个银奖!!
本题线段树,好长时间都没写过线段树题了,暑假时写过一道,那时写了几个小时没写出来, 之后再碰见线段树题都有点胆怯了,这几天有时间的话再把那题重做一遍。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027
题目大意:给一个长度为n的序列s,有m次询问,每次询问给出三个数,a,b,c,
如果a==1,即输出s[b]+s[b+1]+...+s[c]的和。
如果a==0,即把s[b],s[b+1],...s[c]每个数开方取整!
思路:由于数据量很大,很明显要用到线段树,由于序列中的每个数最大为2^64,经过7,8次开方就变成1了,之后再对1开方就不变了!建立线段树之后 每个叶子节点最多只需要访问8次, 可以给每个节点加一个域,用来判断该节点包含的所有数
是否都已经为1,之后就很容易了!
code:
# include
# include
# include
//using namespace std;
# define N 100005
struct node{
int cp;
int l,r;
__int64 sum;
}tree[8*N];
__int64 a[N],Max;
void bulid(int l,int r,int t)
{
int mid;
tree[t].l=l;
tree[t].r=r;
tree[t].cp=0;
if(l==r) {
tree[t].sum=a[r];
if(a[r]==1) tree[t].cp=1;
return;
}
mid=(l+r)/2;
bulid(l,mid,2*t);
bulid(mid+1,r,2*t+1);
tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
if(tree[2*t].cp==1 && tree[2*t+1].cp==1) tree[t].cp=1;
}
void updata(int l,int r,int t)
{
__int64 ans;
if(tree[t].cp==1) return;
if(tree[t].l==tree[t].r)
{
ans=tree[t].sum;
ans=(__int64)sqrt((double)ans);
if(ans==1) tree[t].cp=1;
tree[t].sum=ans;
return;
}
if(r<=tree[2*t].r) updata(l,r,2*t);
else if(l>=tree[2*t+1].l) updata(l,r,2*t+1);
else
{
updata(l,tree[2*t].r,2*t);
updata(tree[2*t+1].l,r,2*t+1);
}
tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
if(tree[2*t].cp==1 && tree[2*t+1].cp==1) tree[t].cp=1;
}
void query(int l,int r,int t)
{
if(tree[t].l==l && tree[t].r==r)
{
if(tree[t].cp==1) {Max+=tree[t].sum;return;}
else if(tree[t].l==tree[t].r) {Max+=tree[t].sum;return;}
}
if(r<=tree[2*t].r) query(l,r,2*t);
else if(l>=tree[2*t+1].l) query(l,r,2*t+1);
else
{
query(l,tree[2*t].r,2*t);
query(tree[2*t+1].l,r,2*t+1);
}
}
int main()
{
int i,n,Q,ch,from,to,ncase=0,tmp;
while(scanf("%d",&n)!=EOF)
{
ncase++;
for(i=1;i<=n;i++)
scanf("%I64d",&a[i]);
bulid(1,n,1);
scanf("%d",&Q);
printf("Case #%d:\n",ncase);
while(Q--)
{
scanf("%d%d%d",&ch,&from,&to);
if(from>to) {tmp=from;from=to;to=tmp;}
if(ch==0) updata(from,to,1);
else
{
Max=0;
query(from,to,1);
printf("%I64d\n",Max);
}
}
printf("\n");
}
return 0;
}