您的位置:首页 > 其它

[codevs]行星序列

2016-04-15 15:31 239 查看
2216 行星序列 2009年省队选拔赛安徽

题目描述 Description

“神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小宇航员夏令营”,在这里小可可不仅学到了丰富的宇航知识,还参与解决了一些模拟飞行中发现的问题,今天指导老师交给他一个任务,在这次模拟飞行的路线上有N个行星,暂且称它们为一个行星序列,并将他们从1至n标号,在宇宙未知力量的作用下这N个行星的质量是不断变化的,所以他们对飞船产生的引力也会不断变化,小可可的任务就是在飞行途中计算这个行星序列中某段行星的质量和,以便能及时修正飞船的飞行线路,最终到达目的地,行星序列质量变化有两种形式:

1,行星序列中某一段行星的质量全部乘以一个值

2,行星序列中某一段行星的质量全部加上一个值

由于行星的质量和很大,所以求出某段行星的质量和后只要输出这个值模P的结果即可,小可可被这个任务难住了,聪明的你能够帮他完成这个任务吗?

输入描述 Input Description

第一行两个整数N和P(1<=p<=1000000000);

第二行含有N个非负整数,从左到右依次为a1,a2,…………,an(0<=ai<=100000000,1<=i<=n),其中ai表示第i个行星的质量:

第三行有一个整数m,表示模拟行星质量变化以及求质量和等操作的总次数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:

操作1:1 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai*c

操作2:2 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai+c

操作3:3 t g 表示输出所有满足t<=i<=g的ai的和模p的值

其中:1<=t<=g<=N,0<=c<=10000000

注:同一行相邻的两数之间用一个空格隔开,每行开头和末尾没有多余空格

输出描述 Output Description

对每个操作3,按照它在输入中出现的顺序,依次一行输出一个整数表示所求行星质量和

样例输入 Sample Input

7 43

1 2 3 4 5 6 7

5

1 2 5 5

3 2 4

2 3 7 9

3 1 3

3 4 7

样例输出 Sample Output

2

35

8

数据范围及提示 Data Size & Hint

100%的数据中,M,N<=100000

40%的数据中,M,N<=10000

————————

概括一下

线段树 区间加&& 区间乘

思想难度在 x + y == x * 1 + y;

x * y == (x + 0)* y;

Just for fun

orz LOI_xczhw

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define L(x) (x << 1)
#define R(x) (x << 1 | 1)
#define sz(x) (tree[x].r - tree[x].l + 1)
typedef long long LL; //QAQ其实这行是懒得打那么多的long long
const LL MAXN = 200000 + 5;
using namespace std;
LL n,Q,m,r,t,g,c;
LL num[MAXN];

struct dot
{
LL l,r;
LL sum,add,mult;
}tree[MAXN << 2];//结构体大法好

void update(LL p)
{
tree[p].sum = (tree[L(p)].sum + tree[R(p)].sum) % Q;
return;
}//更新,校正,修正——百度翻译
//处理完后更新标记 以便下一次处理

void build(LL l,LL r,LL p)
{
tree[p].mult = 1;
tree[p].l = l;
tree[p].r = r;
if(l == r)
{
tree[p].sum = num[l];
return;
}
LL mid = (l + r) >> 1;
build(l,mid,L(p));
build(mid + 1,r,R(p));
update(p);
return;
}//构建线段树

void spread(int p)
{
tree[L(p)].mult = (tree[L(p)].mult * tree[p].mult) % Q;
tree[L(p)].add = ((tree[L(p)].add * tree[p].mult) % Q + tree[p].add % Q) % Q;
tree[L(p)].sum = ((tree[L(p)].sum * tree[p].mult) % Q + (tree[p].add * sz(L(p))) % Q) % Q;

tree[R(p)].mult = (tree[R(p)].mult * tree[p].mult) % Q;
tree[R(p)].add = ((tree[R(p)].add * tree[p].mult) % Q + tree[p].add % Q) % Q;
tree[R(p)].sum = ((tree[R(p)].sum * tree[p].mult) % Q + (tree[p].add * sz(R(p))) % Q) % Q;

tree[p].add = 0;
tree[p].mult = 1;
return;
}//各种标记

void change(LL l,LL r,LL add,LL mult,LL p)
{
if(l <= tree[p].l && tree[p].r <= r)
{
tree[p].mult = (tree[p].mult * mult) % Q ;
tree[p].add = ((tree[p].add * mult) % Q + add % Q) % Q;
tree[p].sum = ((tree[p].sum * mult) % Q + (add * sz(p)) % Q) % Q;
return;
}//多取模防爆
spread(p);
LL mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid)
change(l,r,add,mult,L(p));
if(mid < r)
change(l,r,add,mult,R(p));
update(p);
return;
}//更改

int ask(LL l,LL r,LL p)
{
if(l <= tree[p].l && tree[p].r <= r)
return tree[p].sum;
spread(p);
LL mid = (tree[p].l + tree[p].r) >> 1;
LL ans = 0;

if(l <= mid)
ans += ask(l,r,L(p));
if(mid < r)
ans += ask(l,r,R(p));
update(p);
return ans;
}//询问

int main()
{
memset(num,0,sizeof(num));
scanf("%d %d",&n,&Q);
for(LL i = 1; i <= n; i ++)
scanf("%d",&num[i]);
build(1,n,1);
scanf("%d",&m);

for(LL i = 1; i <= m; i ++)
{
scanf("%lld",&r);
if(r == 1)
{
scanf("%lld %lld %lld",&t,&g,&c);
change(t,g,0ll,c,1);
}
else if(r == 2)
{
scanf("%lld %lld %lld",&t,&g,&c);
change(t,g,c,1ll,1);
}
else if(r == 3)
{
scanf("%lld %lld",&t,&g);
printf("%lld\n",ask(t,g,1) % Q);
}
}
return 0;
}//END
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: