单点更新+区间求最值与和_线段树

来源:互联网 发布:linux vi 设置行号 编辑:程序博客网 时间:2024/04/29 17:02

除了平时做练习赛外,现在主要学习数论与数据结构,数据结构丢了好久了,重新学习还是发现了很多问题!

/*

题意:在每个测试的第一行,是两个正整数 N 和 M ( 0< N <= 100000, 0 < M <= 100000 ),分别代表学生的数目和操作的数目。

学生ID编号分别从 1 编到 N。
第二行包含 N 个整数(范围在 0 到 100 ),代表这 N 个学生的初始成绩,其中第 i 个数代表 ID 为 i 的学生的成绩。
接下来有 M 行,每行有三个数,意思如下:
先输入一个数X,然后分两种情况:【1】【2】       (1 <= X <= 2^31-1)
【1】若X^X%999997是一个素数,则再输入两个数a,b, 
意思是将ID为 a 的学生的成绩更新成b  (1 <= a <= N,  0 <= b <= 100)  
【2】若X^X%999997不是一个素数,则再输入两个数le,ri, 
意思是输出区间【le,ri】中的学生的最低成绩、最高成绩、成绩总和 (1 <= le <= ri <= N)


Sample Input
2 8
69 24 
131744484  1 1
598487296  2 2
542004961  2 2
241081  1 2
23299929  2 36
213276816  1 2
85264  1 2
350288656  1 2


Sample Output
69 69 69
24 24 24
24 24 24
24 69 93
36 69 105
36 69 105
36 69 105
Hint
【特别说明】

【1】在本题中,我们认为0和1也是素数!!!!

*/

#include<stdio.h>#include<string.h>using namespace std;#define maxn 100005#define maxn1 1000005#define mod 999997#define LL __int64struct data{int l,r,minp,maxp,sump;} tree[3*maxn];int a[maxn];bool prime[maxn1];int min(int p,int q) { return p<q?p:q; }int max(int p,int q) { return p>q?p:q; }void Init(){int i,tmp;memset(prime,false,sizeof(prime));for(i=2;i<maxn1;i++)if(!prime[i]){tmp=i*2;while(tmp<maxn1){prime[tmp]=true;tmp+=i;}}}LL MOD(int a,int r){LL d=1,t=(LL)a;while(r){if(r%2)d=(d*t)%mod;r/=2;t=t*t%mod;}return d%mod;}void BuildTree(int p,int l,int r){tree[p].l=l,tree[p].r=r;if(l==r){tree[p].minp=tree[p].maxp=tree[p].sump=a[l];return;}int mid=(l+r)>>1;BuildTree(p<<1,l,mid);BuildTree(p<<1|1,mid+1,r);tree[p].minp=min(tree[p<<1].minp,tree[p<<1|1].minp);tree[p].maxp=max(tree[p<<1].maxp,tree[p<<1|1].maxp);tree[p].sump=tree[p<<1].sump+tree[p<<1|1].sump;}void change(int p,int i,int x){if(tree[p].l==tree[p].r){tree[p].minp=tree[p].maxp=tree[p].sump=x;return;}if(i<=tree[p<<1].r)change(p<<1,i,x);elsechange(p<<1|1,i,x);tree[p].minp=min(tree[p<<1].minp,tree[p<<1|1].minp);tree[p].maxp=max(tree[p<<1].maxp,tree[p<<1|1].maxp);tree[p].sump=tree[p<<1].sump+tree[p<<1|1].sump;}data query(int p,int l,int r){if(tree[p].l==l&&tree[p].r==r)return tree[p];if(r<=tree[p<<1].r)return query(p<<1,l,r);if(l>=tree[p<<1|1].l)return query(p<<1|1,l,r);int mid=(tree[p].l+tree[p].r)>>1;data a=query(p<<1,l,mid),b=query(p>>1,mid+1,r);a.sump+=b.sump;a.minp=min(a.minp,b.minp);a.maxp=max(a.maxp,b.maxp);return a;}int main(){Init();int n,m,i,id,x,y;while(~scanf("%d%d",&n,&m)){for(i=1;i<=n;i++)scanf("%d",&a[i]);BuildTree(1,1,n);while(m--){scanf("%d%d%d",&id,&x,&y);if(!prime[MOD(id,id)]) //对x^x%mod做素数判断change(1,x,y);else{data ans;ans=query(1,x,y);printf("%d %d %d\n",ans.minp,ans.maxp,ans.sump);}}}return 0;}


原创粉丝点击