Curious Array Codeforces - 407C(高阶差分(?)) || sequence
https://codeforces.com/problemset/problem/407/C
(自用,勿看)
手模一下找一找规律,可以发现,对于一个修改(l,r,k),相当于在[l,r]内各位分别加上[1,0,0,0,0,..]做k+1次前缀和得到的数组
比如(l=3,r=6,k=2),[1,0,0,..]做k+1=3次前缀和后为[1,3,6,10,15,..],因此这次修改相当于a[l]+=1,a[l+1]+=3,a[l+2]+=6,a[l+3]+=10
很容易想到k从大到小排序,用差分维护,不断做前缀和“解包”(不展开写了..)
然后我就不会了。。因为每一次是“区间加”,我只能做到从某个位置到末尾全部加,没有办法把多余的消掉
膜了大佬,发现只要每一层差分的时候都在合适位置减去合适值就行了,找规律(例如l=3,r=6,k=2,一开始是1,0,0,0,-1,第一次变成1,1,1,1,0,再变成1,1,1,1,-4,第二次变成1,2,3,4,0,再变成1,2,3,4,-10,第三次变成1,3,6,10,0)(考虑第p次,[1,0,0,0..]做p+1次前缀和得到数组c,那么在r+1位置处减去c[r-l+1],第0次(即第1次开始前)也要减)
然后多个同一阶的差分数列可以直接相加,因此就有了O((n+m)k)的做法
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<ll,ll> pll; 13 const ll md=1000000007; 14 ll n,m; 15 vector<pll> a1[102]; 16 ll an[102][100100]; 17 ll tt[102][100100];//tt[i]是对1,0,0,0,..做i+1次前缀和得到的数组 18 ll a[100100]; 19 int main() 20 { 21 ll i,j,k,x,y,z;pll t; 22 scanf("%lld%lld",&n,&m); 23 for(i=1;i<=n;i++) 24 scanf("%lld",&a[i]); 25 for(i=1;i<=n;i++) 26 tt[0][i]=1; 27 for(i=1;i<=100;i++) 28 { 29 for(j=1;j<=n;j++) 30 { 31 tt[i][j]=(tt[i][j-1]+tt[i-1][j]); 32 (tt[i][j]>=md) && (tt[i][j]-=md); 33 //printf("at%lld %lld %lld\n",i,j,tt[i][j]); 34 } 35 } 36 for(i=1;i<=m;i++) 37 { 38 scanf("%lld%lld%lld",&x,&y,&z); 39 a1[z].pb(mp(x,y)); 40 } 41 for(i=100;i>=0;i--) 42 { 43 for(j=0;j<a1[i].size();j++) 44 { 45 x=a1[i][j].fi;y=a1[i][j].se; 46 ++an[i][x]; 47 (an[i][x]>=md) && (an[i][x]-=md); 48 ++y; 49 for(k=i;k>=0;k--) 50 { 51 an[k][y]-=tt[i-k][y-x]; 52 //printf("2t%lld %lld %lld\n",i-k,y-x,tt[i-k][y-x]); 53 //printf("1t%lld %lld %lld\n",k,y,tt[i-k][y-x]); 54 (an[k][y]<0) && (an[k][y]+=md); 55 } 56 } 57 for(k=1;k<=n;k++) 58 { 59 an[i][k]+=an[i][k-1]; 60 (an[i][k]>=md) && (an[i][k]-=md); 61 } 62 if(i!=0) 63 { 64 for(k=1;k<=n;k++) 65 { 66 an[i-1][k]+=an[i][k]; 67 (an[i-1][k]>=md) && (an[i-1][k]-=md); 68 } 69 } 70 //printf("1t%lld\n",i); 71 //for(k=1;k<=n;k++) 72 // printf("%lld ",an[i][k]); 73 //puts(""); 74 } 75 for(i=1;i<=n;i++) 76 { 77 a[i]+=an[0][i]; 78 (a[i]>=md) && (a[i]-=md); 79 } 80 for(i=1;i<=n;i++) 81 printf("%lld ",a[i]); 82 return 0; 83 }
http://210.33.19.103/contest/1025
A题(sequence)同此题