1. 程式人生 > >LYOI2016 Summer 一次函數 (線段樹)

LYOI2016 Summer 一次函數 (線段樹)

truct mage upd ++ build rect %d har tle

題目描述

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 <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const ll mod = 1e9+7;
 6 const int maxn = 210000;
 7 int kk[maxn],bb[maxn];
 8 int n,m;
 9 char op[5];
10 struct node
11 { 12 int l,r; 13 ll k,b; 14 }tree[maxn<<2]; 15 node Union (node x,node y) 16 { 17 node tmp; 18 tmp.l=x.l,tmp.r=y.r; 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 now) 24 { 25 tree[now] = Union(tree[now<<1
],tree[now<<1|1]); 26 } 27 void build (int now,int L,int R) 28 { 29 if (L==R){ 30 tree[now].l=L,tree[now].r=L; 31 tree[now].k=kk[L];tree[now].b=bb[L]; 32 return ; 33 } 34 int mid = (L+R)>>1; 35 build(now<<1,L,mid); 36 build(now<<1|1,mid+1,R); 37 pushup(now); 38 } 39 void update (int now,int pos,int kkk,int bbb) 40 { 41 if (tree[now].l==tree[now].r){ 42 tree[now].k=kkk,tree[now].b=bbb; 43 return; 44 } 45 int mid = (tree[now].l+tree[now].r)/2; 46 if (pos<=mid) 47 update(now<<1,pos,kkk,bbb); 48 else 49 update(now<<1|1,pos,kkk,bbb); 50 pushup(now); 51 } 52 node query (int now,int L,int R) 53 { 54 if (tree[now].l==L&&tree[now].r==R) 55 return tree[now]; 56 int mid = (tree[now].l+tree[now].r)/2; 57 if (R<=mid) 58 return query(now<<1,L,R); 59 else if (L>mid) 60 return query(now<<1|1,L,R); 61 else 62 return Union(query(now<<1,L,mid),query(now<<1|1,mid+1,R)); 63 } 64 int main() 65 { 66 //freopen("de.txt","r",stdin); 67 scanf("%d%d",&n,&m); 68 for (int i=1;i<=n;++i) 69 scanf("%d%d",&kk[i],&bb[i]); 70 build(1,1,n); 71 for (int i=0;i<m;++i){ 72 scanf("%s",op); 73 if (op[0]==M){ 74 int x,y,z; 75 scanf("%d%d%d",&x,&y,&z); 76 update(1,x,y,z); 77 } 78 else{ 79 int lll,rrr,xx; 80 scanf("%d%d%d",&lll,&rrr,&xx); 81 node anss=query(1,lll,rrr); 82 ll ans = ((anss.k*xx)%mod+anss.b)%mod; 83 printf("%lld\n",ans); 84 } 85 } 86 return 0; 87 }

LYOI2016 Summer 一次函數 (線段樹)