牛客練習賽48 C.小w的糖果(動態維護差分陣列)
阿新 • • 發佈:2021-01-21
操作一亂搞就行了
操作二咋辦…也是亂搞就行了,維護一個當前的操作二數目 n u m num num和上一個人因為操作二加了多少 x x x
那麼當前人需要加上 x + n u m x+num x+num,所以操作二也可以線性維護
操作三…沒辦法弄,差值不固定,無法下手
考慮差分陣列 a a a
操作一隻需要在 a [ l ] + + a[l]++ a[l]++即可
操作二隻需要在 i ∈ [ l , r ] i\in[l,r] i∈[l,r]的每個 a [ i ] + + a[i]++ a[i]++即可,線性掃一遍可以動態維護
操作三怎麼搞
要知道在 l l l落下一個操作三,那麼之後的 a l + i a_{l+i} al+i需要比 a l + i − 1 a_{l+i-1} al+i−1多 ( i + 1 ) 2 − i 2 = 2 i + 1 (i+1)^2-i^2=2i+1 (i+1)2−i2=2i+1
也就是 l l l之後的每個數穩定比前面多 2 i + 1 2i+1 2i+1,而且 l l l位置加上一,後面每個位置加 2 2 2
設截至上一次同時維護
n
u
m
num
num個操作三,在當前位置插入
r
r
r個操作三,
a
[
i
−
1
]
a[i-1]
a[i−1]由於操作三加上了
x
x
x
那麼 a [ i ] a[i] a[i]需要由於操作三加上 x + 2 ∗ n u m + r x+2*num+r x+2∗num+r
所以可以掃一遍動態維護差分陣列。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5+10;
const int mod = 1e9+7;
int t,n,m,x[maxn],a[maxn][4],cha[maxn];
signed main()
{
cin >> t;
while( t-- )
{
cin >> n >> m;
for(int i=1;i<=m;i++)
{
int type,pos; cin >> type >> pos; a[pos][type]++;
}
for(int i=1;i<=n;i++)
{
x[i] = ( x[i-1]+2*a[i-1][3]+a[i][3] )%mod;//操作三
cha[i] = x[i];
for(int j=2;j<=3;j++) a[i][j] += a[i-1][j];
cha[i] = (cha[i]+a[i][1] )%mod;//操作一
cha[i] = ( cha[i]+a[i][2] )%mod;//操作二
}
int sum = 0;
for(int i=1;i<=n;i++)
{
cha[i] = ( cha[i]+cha[i-1] )%mod;
printf("%d ",cha[i]);
}
puts("");
for(int i=1;i<=n;i++) a[i][1]=a[i][2]=a[i][3]=cha[i]=x[i]=0;
}
}