LYOI 2016 Summer 函数 【线段树】

<题目链接>

题目大意:

fqk 退役后开始补习文化课啦,于是他打开了数学必修一开始复习函数,他回想起了一次函数都是 f(x)=kx+b的形式,现在他给了你n个一次函数 fi(x)=kix+b,然后将给你m个操作,操作将以如下格式给出:
    1.M i k b,把第i个函数改为 fi(x)=kx+b。
    2.Q l r x,询问 fr(fr−1(…fl(x))) mod 1000000007的值。
输入
第一行两个整数n,m,代表一次函数的数量和操作的数量。
接下来n行,每行两个整数,表示 ki,bi。
接下来m行,每行的格式为 M i k b 或 Q l r x。

输出

对于每个操作Q,输出一行表示答案。
输入

5 5
4 2
3 6
5 7
2 6
7 5
Q 1 5 1
Q 3 3 2
M 3 10 6
Q 1 4 3
Q 3 4 4
输出
1825
17
978
98
n,m≤200000,k,b,x<1000000007。
解题分析:
其实就是简单的单点修改和区间查询,只不过需要将每个节点对应的函数嵌套后得到的表达式看成普通线段树每个节点对应区间的区间和,只要抽象的转化为这个模型,本题就好做了。
 1 #include <cstring>
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define Lson rt<<1,l,mid
 8 #define Rson rt<<1|1,mid+1,r
 9 typedef long long ll;
10 const ll mod = 1e9+7;
11 const int M = 2e5+10;
12 int cur1[M],cur2[M];
13 int n,m;
14 struct node{
15     ll k,b;
16 }tr[M<<2];
17 node cal(node x,node y){    //将Fy(Fx)的嵌套关系合并,其实就是将里面的一元一次函数乘出来
18     node tmp;
19     tmp.k=(x.k*y.k)%mod;    
20     tmp.b=((y.k*x.b)%mod+y.b)%mod;
21     return tmp;
22 }
23 void Pushup(int rt){    //根据函数嵌套关系维护函数嵌套值,相当于该区间对应函数的嵌套值看成普通线段树的区间和(这个思路非常妙)
24     tr[rt] = cal(tr[rt<<1],tr[rt<<1|1]);
25 }
26 void build(int rt,int l,int r){
27     if (l==r){
28         tr[rt].k=cur1[l],tr[rt].b=cur2[l];
29         return;
30     }
31     int mid = (l+r)>>1;
32     build(Lson);
33     build(Rson);
34     Pushup(rt);
35 }
36 void update(int rt,int l,int r,int loc,int tmp1,int tmp2)
37 {
38     if (l==r){
39         tr[rt].k=tmp1,tr[rt].b=tmp2;   //单点更新该函数的系数
40         return;
41     }
42     int mid = (l+r)>>1;
43     if (loc<=mid) update(Lson,loc,tmp1,tmp2);
44     else update(Rson,loc,tmp1,tmp2);
45     Pushup(rt);
46 }
47 node query (int rt,int l,int r,int L,int R)
48 {
49     if (l==L&&r==R)return tr[rt];
50     int mid = (l+r)>>1;
51     if (R<=mid)return query(Lson,L,R);
52     else if (L>mid)return query(Rson,L,R);
53     else return cal(query(Lson,L,mid),query(Rson,mid+1,R));
54 }
55 /*node query(int rt,int l,int r,int L,int R){      //为什么我这样查询区间函数嵌套和不行???
56     if(l<=l&&r<=R)return tr[rt];
57     int mid=(l+r)>>1;
58     node tmp;
59     tmp.k=1,tmp.b=0;
60     if(L<=mid)tmp=cal(query(Lson,L,R),tmp);
61     if(R>mid)tmp=cal(query(Rson,L,R),tmp);
62     return tmp; 
63 }*/
64 int main()
65 {
66     scanf("%d%d",&n,&m);
67     for (int i=1;i<=n;++i)
68         scanf("%d%d",&cur1[i],&cur2[i]);
69     build(1,1,n);
70     char op[10];
71     while(m--){
72         scanf("%s",op);
73         int x,y,c;    
74         scanf("%d%d%d",&x,&y,&c);
75         if (op[0]=='M'){
76             update(1,1,n,x,y,c);
77         }
78         else{
79             node tmp=query(1,1,n,x,y);
80             ll ans = ((tmp.k*c)%mod+tmp.b)%mod;
81             printf("%lld
",ans);
82         }
83     }
84     return 0;
85 }



2018-10-13
原文地址:https://www.cnblogs.com/00isok/p/9784370.html