1. 程式人生 > 其它 >牛客練習賽48 C.小w的糖果(動態維護差分陣列)

牛客練習賽48 C.小w的糖果(動態維護差分陣列)

技術標籤:牛客練習比較有意思的題(可以禍害學弟學妹的題)

傳送門

操作一亂搞就行了

操作二咋辦…也是亂搞就行了,維護一個當前的操作二數目 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+i1 ( i + 1 ) 2 − i 2 = 2 i + 1 (i+1)^2-i^2=2i+1 (i+1)2i2=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[i1]由於操作三加上了 x x

x

那麼 a [ i ] a[i] a[i]需要由於操作三加上 x + 2 ∗ n u m + r x+2*num+r x+2num+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; } }