用指针写线段树(维护乘法)
今天肖神给我讲课,讲了一个用指针写的线段树,写起来比数组复杂,但是貌似动态开点操作好像简单一些。之前我也写过用指针的数据结构,所以理解起来不是很难。
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k 操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k 操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果 输出格式: 输出包含若干行整数,即为所有操作3的结果。 输入输出样例 输入样例#1: 复制 5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4 输出样例#1: 复制 17 2 说明 时空限制:1000ms,128M 数据规模: 对于30%的数据:N<=8,M<=10 对于70%的数据:N<=1000,M<=10000 对于100%的数据:N<=100000,M<=100000 (数据已经过加强^_^) 样例说明: 故输出应为17、2(40 mod 38=2)
直接写代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) typedef long long ll; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(),c > '9' || c < '0') if(c == '-') op = 1; x = c - '0'; while(c = getchar(),c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op == 1) x = -x; } struct node { node *lch,*rch; int sum,mul,add; node() { lch = 0; rch = 0; mul = 1; add = 0; } }*root; int n,m,p,a[100010]; void update(node *u) { u->sum = (u->lch->sum + u->rch->sum) % p; } void build(node *&u,int l,int r) { u = new node; if(l == r) { u->sum = a[l]; return; } int mid = (l + r) >> 1; build(u->lch,l,mid); build(u->rch,mid + 1,r); update(u); } void refresh(node *u,int l,int r,int mul,int add) { u->sum = (ll)u->sum * mul % p; u->sum = (u->sum + (ll)add * (r - l + 1)) % p; u->mul = (ll)u->mul * mul % p; u->add = ((ll)u->add * mul + add) % p; } void push_down(node *u,int l,int r) { if(u->mul != 1 || u->add != 0) { int mid = (l + r) >> 1; refresh(u->lch,l,mid,u->mul,u->add); refresh(u->rch,mid + 1,r,u->mul,u->add); u->mul = 1; u->add = 0; } } void modify(node *u,int l,int r,int ql,int qr,int mul,int add) { if(l == ql && r == qr) { refresh(u,l,r,mul,add); return; } push_down(u,l,r); int mid = (l + r) >> 1; if(qr <= mid) { modify(u->lch,l,mid,ql,qr,mul,add); } else if(ql > mid) { modify(u->rch,mid + 1,r,ql,qr,mul,add); } else { modify(u->lch,l,mid,ql,mid,mul,add); modify(u->rch,mid + 1,r,mid + 1,qr,mul,add); } update(u); } int query(node *u,int l,int r,int ql,int qr) { if(l == ql && r == qr) { return u->sum; } push_down(u,l,r); int mid = (l + r) >> 1; if(qr <= mid) { return query(u->lch,l,mid,ql,qr); } else if(ql > mid) { return query(u->rch,mid + 1,r,ql,qr); } else { return (query(u->lch,l,mid,ql,mid) + query(u->rch,mid + 1,r,mid + 1,qr)) % p; } } int main() { read(n);read(m);read(p); duke(i,1,n) read(a[i]); build(root,1,n); int op,l,x,r; while(m--) { read(op);read(l);read(r); if(op == 1) { read(x); modify(root,1,n,l,r,x,0); } else if(op == 2) { read(x); modify(root,1,n,l,r,1,x); } else { printf("%d\n",query(root,1,n,l,r)); } } return 0; }
只想找一个不会伤害我的人