codeforces 446 c

题目的大意是你需要维护一个序列a,有两种操作:

1.对于区间[l,r],对于l<=i<=r,ai+=f[i-l+1],f是斐波那契数列

2.查询区间[l,r]的和

很久以前在培训的时候写过,然而并不会做,后来一直拖到退役也没有搞懂,今天心血来潮研究了一下,发现还是比较简单的。

很明显,这道题我们需要用线段树来维护,因为有区间操作,所以我们需要打标记,但是我们知道,线段树的标记应该满足可传递性,显然直接打标记是错误的

我们进行一个推倒:

设a,b是斐波那契数列中连续的两项,那么之后的序列应该是这样的:

a , b , a+b , a+2b , 2a+3b , 3a+5b...

我们发现从第三项开始a的系数是1,1,2,3,5

b的系数是1,2,3,5

也就是说其后的第i项应该是:a*f[i-2]+b*f[i-1]

那么我们对其后的n项求一个和,那么就应该是:a*(f[1]+f[2]+f[3]+...+f[n-2])+b*(f[1]+f[2]+f[3]+...+f[n-1])

那么我们发现想要维护一个区间[l,r]的标记我们只需要维护a和b即可,其后的取决于区间的长度

比如我们标记了[l,r]

那当我们下传标记的时候应该怎么做呢?

[l,(l+r)>>1] 的a和b直接下传即可

[(l+r)>>1|1,r]的a和b就要变化了,因为这里的(l+r)>>1|1实际上是[l,r]的第(l+r)>>1|1-l+1项,所以a就是(l+r)>>1|1-l+1,b是a+1

这样就可以做到下标的传递了,每次标记直接相加即可。

这道题也就解决了,代码过几天再写。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<string>
  6 #include<algorithm>
  7 #define mod 1000000009
  8 #define ll long long
  9 using namespace std;
 10 struct tree{
 11     int l,r;
 12     ll taga,tagb;
 13     ll sum;
 14 }f[1200005];
 15 int n,m;
 16 ll fib[300005],a[300005],sf[300005];
 17 void update(int i,int ta,int tb){
 18     int len=f[i].r-f[i].l+1;
 19     //cout<<f[i].sum<<endl;
 20     if(len>=2){
 21         ll tmp1=(ta*sf[len-2])%mod,tmp2=(tb*sf[len-1])%mod;
 22         tmp1=(tmp1+tmp2)%mod;
 23         //cout<<tmp1<<endl;
 24         f[i].sum=(f[i].sum+tmp1)%mod;
 25         f[i].sum=(f[i].sum+ta)%mod;
 26     }
 27     else{
 28         f[i].sum=(f[i].sum+ta)%mod;
 29         f[i].sum=(f[i].sum+tb*(len-1))%mod;
 30     }
 31     //cout<<f[i].sum<<endl;
 32     f[i].taga=(f[i].taga+ta)%mod;
 33     f[i].tagb=(f[i].tagb+tb)%mod;
 34     return ;
 35 }
 36 void pushup(int i){
 37     f[i].sum=(f[i<<1].sum+f[i<<1|1].sum)%mod;
 38     return ;
 39 }
 40 void pushdown(int i){
 41     if(f[i].taga){
 42         update(i<<1,f[i].taga,f[i].tagb);
 43         int mid=(f[i].r+f[i].l)>>1,len=(mid-f[i].l+1);
 44         //if(len>=2){
 45             ll tmp1=((f[i].taga*fib[len-1])%mod+(f[i].tagb*fib[len])%mod)%mod;
 46             ll tmp2=((f[i].taga*fib[len])%mod+(f[i].tagb*fib[len+1])%mod)%mod;
 47             update(i<<1|1,tmp1%mod,tmp2%mod);
 48        // }
 49         //else update(i<<1|1,f[i].tagb,(f[i].taga+f[i].tagb)%mod);
 50         f[i].taga=0;f[i].tagb=0;
 51         return ;
 52     }
 53     else return ;
 54 }
 55 void build(int i,int left,int right){
 56     f[i].l=left;f[i].r=right;
 57     if(left==right){
 58         f[i].sum=a[left];
 59         return ;
 60     }
 61     int mid=(left+right)>>1;
 62     build(i<<1,left,mid);build(i<<1|1,mid+1,right);
 63     pushup(i);
 64     //cout<<f[i].sum<<f[i<<1].sum<<f[i<<1|1].sum<<endl;
 65     return ;
 66 }
 67 void add(int i,int left,int right,int num){
 68     if(f[i].l==left&&f[i].r==right){
 69         update(i,fib[num],fib[num+1]);
 70         return ;
 71     }
 72     pushdown(i);
 73     int mid=f[i<<1].r,len=(mid-left+1);
 74     if(right<=mid)add(i<<1,left,right,num);
 75     else if(left>mid)add(i<<1|1,left,right,num);
 76     else add(i<<1,left,mid,num),add(i<<1|1,mid+1,right,num+len);
 77     pushup(i);
 78 }
 79 ll query(int i,int left,int right){
 80     if(f[i].l==left&&f[i].r==right)return f[i].sum;
 81     pushdown(i);
 82     int mid=(f[i].l+f[i].r)>>1;
 83     if(right<=mid)return query(i<<1,left,right);
 84     else if(mid<left)return query(i<<1|1,left,right);
 85     else return (query(i<<1,left,mid)+query(i<<1|1,mid+1,right))%mod;
 86 }
 87 int main(){
 88     //freopen("input.txt","r",stdin);
 89     fib[1]=1;fib[2]=1;sf[1]=1;sf[2]=2;
 90     ios_base::sync_with_stdio(false);
 91     cin.tie(0);
 92     cin>>n>>m;
 93     for(int i=1;i<=n;i++)
 94         cin>>a[i];
 95     for(int i=3;i<=n+3;i++){
 96         fib[i]=(fib[i-1]+fib[i-2])%mod;
 97         sf[i]=(sf[i-1]+fib[i])%mod;
 98     }
 99     build(1,1,n);
100     for(int i=1;i<=m;i++){
101         int x,y,z;
102         cin>>x>>y>>z;
103          //cout<<"SSS"<<endl;
104         if(x==1)add(1,y,z,1);
105         else cout<<query(1,y,z)<<'\n';
106          //cout<<"SSS"<<endl;
107     }
108     return 0;
109 }
View Code

 

转载于:https://www.cnblogs.com/htwx/articles/7624561.html

### Codeforces 2045C Saraga Problem Explanation The provided references do not contain information regarding the specific problem "Saraga" with ID 2045C from Codeforces. However, based on common practices for solving problems on platforms like Codeforces, a structured approach to understanding and potentially solving this problem involves several key steps. #### Understanding the Problem Statement To effectively tackle any competitive programming challenge, comprehending the exact requirements as outlined in the official problem statement is crucial. For an unspecified problem such as "Saraga," one should start by carefully reading through all sections including constraints, inputs, outputs, examples, and notes available directly from the source at [Codeforces](https://codeforces.com/) under contest number 2045, problem C[^1]. #### Analyzing Constraints Typically, analyzing given limits helps determine which algorithms might fit within those boundaries efficiently. Problems often specify maximum values for variables used in calculations or array sizes that influence algorithm choice significantly. #### Identifying Patterns Through Examples Examining sample cases usually provides insights into how solutions behave across different scenarios. This step aids immensely when formulating hypotheses about underlying patterns or properties exploited during implementation. #### Formulating Hypotheses Based on Similarities With Known Concepts Given no direct reference material exists specifically addressing "Saraga," drawing parallels between its description—if accessible—and other well-documented topics could offer valuable clues towards crafting effective strategies. Bitwise operations have been mentioned extensively throughout previous discussions; therefore, considering their applicability remains reasonable depending upon actual task specifications[^5]. ```cpp // Example pseudo-code structure without concrete logic due to lack of detailed problem definition. #include <bits/stdc++.h> using namespace std; int main() { // Placeholder code block illustrating general setup rather than precise functionality related to 'Saraga'. } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值