2111: Pikachu
时间限制: 1 Sec 内存限制: 128 MB
提交: 145 解决: 41
[提交] [状态] [讨论版] [命题人:admin]
题目描述
采蘑菇的小西佬去看了皮卡丘大侦探,然后他深深的喜欢上了皮卡丘,现在他想让你数一数n幢房子内的皮卡丘的个数。
但是小西佬突然觉得太简单了,他稍微增加了难度。现在有两种操作: 第一种操作对[l,r]区间内每幢房子塞入一个皮卡丘; 第二种操作对第l次到第r次的操作重复一遍。
问依次进行m次操作后每幢房子内皮卡丘的个数。数据保证l < r 且对于第二种操作所给区间一定是之前的操作,对于第一种操作r一定<=n。初始房子为空。
输入
T<=50组数据,n<=100000, m <= 100000。 依次输入一个T,n,m,然后m行操作。每行3个数字,分别为id,l,r(id为1则为第一种操作,否则为第二种操作)
输出
依次输出1到n幢房子内的皮卡丘个数,答案对1 000 000 007取模(行末没有多余空格)
样例输入
2
1 2
1 1 1
1 1 1
5 5
1 1 2
1 4 5
2 1 2
2 1 3
2 3 4
样例输出
2
7 7 0 7 7
提示
样例解释:
第二组数据,第一次操作结束后[1,1,0,0,0],第二次操作后[1,1,0,1,1],第三次操作后[2,2,0,2,2],第四次操作后[4,4,0,4,4],第五次操作后[7,7,0,7,7]
浙江理工大学月赛2019年5月
可以 O(1)维护两个差分数组,一个是针对重复操作的差分数组,一个是针对当前房子塞入皮卡丘的个数的差分数组。对第二个差分数组的每次修改的大小是当前操作重复操作次数。 因为每一次第二种操作总是针对之前的操作,所以要倒着跑一遍。 最后对针对当前房子塞入皮卡丘的个数的差分数组求个前缀和就好了。
#include<bits/stdc++.h>
#define fi first
#define se second
#define log2(a) log(n)/log(2)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 1e6 + 10;
const ll mod = 1e9+7;
const int base=131;
const double pi=acos(-1);
map<string, int>ml;
int t,n,m;
int num[N],pre[N];
int op[N],l[N],r[N];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(num,0,sizeof num);
memset(pre,0,sizeof pre);
pre[m+1]=1;
pre[0]--;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&op[i],&l[i],&r[i]);
}
for(int i=m;i>=1;i--)
{
pre[i]=(pre[i]+pre[i+1])%mod;
if(op[i]==1)
{
num[l[i]]=(num[l[i]]+pre[i])%mod;
num[r[i]+1]=(num[r[i]+1]-pre[i]+mod)%mod;
}
else
{
pre[r[i]]=(pre[r[i]]+pre[i])%mod;
pre[l[i]-1]=(pre[l[i]-1]-pre[i]+mod)%mod;
}
}
for(int i=1;i<=n;i++)
{
num[i]=(num[i]+num[i-1])%mod;
printf("%d%c",num[i],i!=n?' ':'\n');
}
}
}