hdu4893 Wow! Such Sequence!

线段树:

     三种操作:1.将第k位的数加上d

                         2.求区间l,r所有数之和

                         3.将区间l,r内所有数变为最近的Fibonacci数

   维护两个变量,第一个是区间内所有数之和sum,第二个如果区间内所有数变为 Fibonacci数 sum的改变量num

我的代码:

  

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
long long sum[300000],num[300000];
bool yes[300000];
long long Fib[1000];
long long Fibo(){
  Fib[0]=Fib[1]=1;
  for (int i=2;i<92;i++) {
      Fib[i]=Fib[i-1]+Fib[i-2];
  }
  return 0;
}
long long  MaxCF(long long x){
  //cout<<"x="<<x<<endl;
  if (x<=1) return 1;
  if (x>=Fib[91]) return Fib[91];
  for (int i=1;i<=91;i++){
    if (x>=Fib[i]&&x<=Fib[i+1]) {
      if (x-Fib[i]>Fib[i+1]-x) return Fib[i+1];
      else return Fib[i];
    }
  }
}
int build (int o,int L,int R){
  yes[o]=false;
  int M=L+(R-L)/2;
  if (L==R) sum[o]=0,num[o]=1;
  else {
    build(o*2,L,M);
    build(o*2+1,M+1,R);
    sum[o]=sum[o*2]+sum[o*2+1];
    num[o]=num[o*2]+num[o*2+1];
  }
  return 0;
}
int maintain(int o,int L,int R){
  int lc=o*2,rc=o*2+1;
  //sum[o]=0;
  //num[o]=0;
  if (R>L) {
    sum[o]=sum[lc]+sum[rc];
    num[o]=num[o*2]+num[o*2+1];
  }
  return 0;
}
long long k,d;
int pushdown(int o,int L,int R){
  int lc=o*2,rc=o*2+1;
  if (yes[o]){
     if (L<R){
     yes[lc]=true;
     yes[rc]=true;
     sum[lc]+=num[lc];
     num[lc]=0;
     sum[rc]+=num[rc];
     num[rc]=0;
     }
     yes[o]=false;
  }
  return 0;
}
long long _sum,y1,y2;
int query(int o,int L,int R){
   if (yes[o]) pushdown(o,L,R);
   if (y1<=L&&y2>=R){
     _sum+=sum[o];
   }
   else {
     int M=L+(R-L)/2;
     if (y1<=M) query(o*2,L,M);
     if (y2>M)  query(o*2+1,M+1,R);
   }
   return 0;
}
int add(int o,int L,int R){
  if (yes[o]) pushdown(o,L,R);
  if (L==R&&L==k){
    sum[o]+=d;
    num[o]=MaxCF(sum[o])-sum[o];
  }
  else {
    int M=L+(R-L)/2;
    if (k<=M) add(o*2,L,M);
    if (k>M)  add(o*2+1,M+1,R);
    maintain(o,L,R);
  }
  return 0;
}
int setF(int o,int L,int R){
   if (yes[o]) return 0;
   if (y1<=L&&y2>=R)  {
       yes[o]=true;
       sum[o]+=num[o];
       num[o]=0;
   }
   else {
       int M=L+(R-L)/2;
       if (y1<=M) setF(o*2,L,M);
       if (y2>M)  setF(o*2+1,M+1,R);
       maintain(o,L,R);
   }
   return 0;
}
int main (){
  Fibo();
  int n,m;
  while (~scanf("%d%d",&n,&m)){
    build (1,1,n);
    for (int i=0;i<m;i++){
     // cout<<"IIIII"<<endl;
      int a,b,c;cin>>a>>b>>c;
      if (a==1){
        k=b;d=c;
        add(1,1,n);
      }
      if (a==3){
        y1=b;y2=c;
        setF(1,1,n);
      }
      if (a==2){
        y1=b;y2=c;
        _sum=0;
        query(1,1,n);
        cout<<_sum<<endl;
      }
    }
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值