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 }
View Code

http://210.33.19.103/contest/1025

A题(sequence)同此题

 

posted @ 2018-10-23 15:38  hehe_54321  阅读(212)  评论(0编辑  收藏  举报
AmazingCounters.com