10.17T3 四颗线段树维护区间+CRT

Description

号外号外,Leo_JAM.Inc全新产品:ZUAFootball19上架了。 
本作采用你从没有用过的全新物理引擎——烈火引擎。 
Problem Description 
而你作为世减(SEJIAN)公司的年度大作SM2019(soccer manager 2019)的开发员也想写一个这么 牛逼的引擎。 
实际上引擎就是泛化数值的过程(我也不知道对不对) 
你构思了一套很富有创意的船新引擎。这款引擎是有史以来第一款考虑了足球场上的风向的引擎 (我也不知道是不是有史以来第一个) 
假设当前是巴塞罗这队当家球星梅东带球,他发现守门员卡东利亚斯站位靠前,起脚远射,哐当入 网。 
这在游戏引擎里可以简化成如下操作,假设梅东是在距离3块草皮处远射的。 
并且当前草皮上风速为 
+2 
*3 
^4(次方运算) 
1. 射门,并且射门力量为X。 
2. 当前第一段草皮的风速是+2所以现在球速变为x+2 
3. 当前第二段草皮刮起了龙卷风(摧毁了停车场)球速变为(x+2)*3 
4. 当前第三段草皮是飓风,球速变为((x+2)*3)^4(注意这不是按位异或) 
5. 卡东利亚斯猝不及防,年事已高,身高太矮,球应声入网。 
如果你注意看转播,会发现这里存在一个这脚射门的球速是多少的显示,实际上在游戏中这也决定了 守门员扑不扑得到球。 
所以这和现实不一样,你不是输出最大的球速而是输出最后的球速。 

但是有句诗说得好: 
迟来白羽多娇气, 
鸽到赛前竟咕声。 

你把这件事忘得一干二净,但是SM2019不上市,整个游戏市场就会被第一人称射击游戏和 ZUAFootball19瓜分。所以你准备魔改引擎,让他简单一点。 
即: 
现在球场被简化描述为n段 

本来这个引擎是用来传球的(即区间询问)不要了 
本来这个引擎是用来远射的(即询问i-n)不要了 
我只用来开大脚吊门。(即只会询问1-n) 
什么不存在这种情况? 
详见选手下发样例。 
而且由于某种原因,对于两队全都是可以加速的球。 
所以这n段描述只会出现+x(顺风球) *x(龙卷风球)^x(飓风球三种)而且x为自然数。 
但是地球OL并不允许某些超出自然法则的事出现(如球速超过光速) 
按照等比例视角,这个世界的光速可以看为29393.我们不希望球速大于光速,这可能导致降维打击和 超时空进球(还没有射门球就进了)等违法乱纪的踢假球行为。 
但是让球速严格小于光速需要动态规划这种困难的算法,你作为咸鱼程序员早已忘得一干二净。 
所以你悄悄咪咪的让球速对29393去模. 
接下来会有Q次操作。 
1 x 这个操作表示一次开大脚,你需要返回x球速从1算到n的答案对29393取模 
2 Id optx这个表示风速改变 第Id号风速变为了optx。 

Input

第一行两个整数n,m. 
第二行至第n+1行每行一个optX 
第n+2行至第n+m+1行每行一个修改操作或询问操作。 
若第一个整数:1 x表示询问射门初始速度为x并回答最终的速度。 
若第一个整数: 2 pos optX表示将pos处的询问改为optX。

Output

对于每个询问输出一行回答。

Sample Input

10 12 ^9 *17 ^20 +19 +4 *5 *18 ^5 *10 *16 2 3 ^5 1 11 2 10 ^26 2 5 +23 2 9 ^28 2 1 +9 1 13 1 13 1 25 2 2 ^9 1 24 2 2 ^3

Sample Output

23534 5014 5014 21555 26419

Hint

 
 
 
 
 
首先29393=19*17*13*7
首先一个显然的结论如果一个数加上模数再进行加乘幂操作搞下来实际上与不加没有区别
所以我们可以考虑维护四颗线段树维护在每个小模数下的整数值经过一段区间后会变成的值,x经过l-r变成什么数,x在[0,mod-1]范围
向上维护的时候先运算左边再运算右边
然后我们每次询问实际上就是访问t[1].val[x%mod]的值
然后四个值出来暴力枚举或者CRT一下就可以了
code:
  1 #include<iostream>
  2 #include<cstdio>
  3 #define lc (p<<1)
  4 #define rc (p<<1|1)
  5 #define N 1000005
  6 using namespace std;
  7 const int MOD=29393;
  8 int ksm(int a,int b,int mod) {
  9     int ans=1;
 10     for(; b; b>>=1) {
 11         if(b&1) {
 12             ans*=a;
 13             ans%=mod;
 14         }
 15         a*=a;
 16         a%=mod;
 17     }
 18     return ans;
 19 }
 20 char operation[N];
 21 int number[N];
 22 struct Segment_Tree {
 23     int mod;
 24     struct node {
 25         int l,r,val[21];
 26     } t[N];
 27     void pushup(int p) {
 28         for(int i=0; i<mod; i++) {
 29             t[p].val[i]=t[rc].val[t[lc].val[i]];
 30         }
 31     }
 32     void pushnow(int p,char op,int num) {
 33         for(int i=0; i<mod; i++) {
 34             if(op=='+') {
 35                 t[p].val[i]=(i+num)%mod;
 36             } else if(op=='*') {
 37                 t[p].val[i]=(i*num)%mod;
 38             } else {
 39                 t[p].val[i]=ksm(i,num,mod);
 40             }
 41         }
 42     }
 43     void build(int p,int l,int r) {
 44     //    cout<<"point->"<<p<<" l->"<<l<<" r->"<<r<<'\n';
 45         t[p].l=l,t[p].r=r;
 46         if(l==r) {
 47             char op=operation[l];
 48             int num=number[l];
 49             pushnow(p,op,num);
 50             return ;
 51         }
 52         int mid=l+r>>1;
 53         build(lc,l,mid);
 54         build(rc,mid+1,r);
 55         pushup(p);
 56     }
 57     void update(int p,int k,int op,int num) {
 58     //    cout<<p<<" "<<k<<" "<<op<<" "<<num<<'\n';
 59         if(t[p].l==t[p].r) {
 60             pushnow(p,op,num);
 61             return ;
 62         }
 63         int mid=t[p].l+t[p].r>>1;
 64         if(k<=mid)update(lc,k,op,num);
 65         if(k>mid)update(rc,k,op,num);
 66         pushup(p);
 67     }
 68 } A,B,C,D;
 69 int Mod[5]= {0,7,13,17,19};
 70 int X[5];
 71 int CRT() {
 72     for(int i=0; i<MOD; i++)
 73         if(i%7==X[1]&&i%13==X[2]&&i%17==X[3]&&i%19==X[4])return i;
 74 }
 75 int main() {
 76     int n,m;
 77     cin>>n>>m;
 78     for(int i=1; i<=n; i++) {
 79         string d;
 80         cin>>d;
 81         operation[i]=d[0];
 82         int x=0;
 83         for(int j=1; j<d.size(); j++)x=x*10+d[j]-'0';
 84         number[i]=x;
 85     }
 86     A.mod=7;B.mod=13;
 87     C.mod=17;D.mod=19;
 88     A.build(1,1,n);B.build(1,1,n);
 89     C.build(1,1,n);D.build(1,1,n);
 90     while(m--) {
 91         int op;
 92         cin>>op;
 93         if(op==1) {
 94             int x;
 95             cin>>x;
 96             X[1]=A.t[1].val[x%7];
 97             X[2]=B.t[1].val[x%13];
 98             X[3]=C.t[1].val[x%17];
 99             X[4]=D.t[1].val[x%19];
100             cout<<CRT()<<'\n';
101         } else {
102             int pos;
103             cin>>pos;
104             string d;
105             cin>>d;
106             int opp=d[0];
107             int x=0;
108             for(int j=1; j<d.size(); j++)x=x*10+d[j]-'0';
109             A.update(1,pos,opp,x);
110             B.update(1,pos,opp,x);
111             C.update(1,pos,opp,x);
112             D.update(1,pos,opp,x);
113 //            cout<<"!";
114         }
115     }
116     return 0;
117 }

over

posted @ 2018-10-17 19:53  saionjisekai  阅读(62)  评论(0编辑  收藏  举报