LYOI2016 Summer 一次函数 (线段树)
Posted 抓不住Jerry的Tom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LYOI2016 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的值。
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。
接下来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 一次函数 (线段树)的主要内容,如果未能解决你的问题,请参考以下文章
Petrozavodsk Summer Training Camp 2016H(多标记线段树)题解