C 小w的糖果
题意:3种操作,第一种是使pos右边的数全部+1,第二种是pos右边的数依次+k(k从1开始递增),第三种是pos右边的数依次+k^2(k从1开始递增)。
解法:第一种我们很容易想到差分,我们顺着差分这个思路往下想,可以发现第二张可以差分之后再差分,第三种就3阶差分。
以第三种为例讲解:原数组:+0 +1 +4 +9 +16 一阶差分:+0 +1 +3 +5 +7 二阶差分:+0 +1 +2 +2 +2 三阶差分:+0 +1 +1 +0 +0 所以我们使c[pos]++,c[pos+1]++,然后做3次前缀和即可还原原数组。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; const int MOD=1e9+7; int n,m,a[N],b[N],c[N]; void getsum(int a[]) { for (int i=1;i<=n;i++) a[i]=(a[i]+a[i-1])%MOD; } int main() { int T; cin>>T; while (T--) { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) a[i]=b[i]=c[i]=0; for (int i=1;i<=m;i++) { int opt,pos; scanf("%d%d",&opt,&pos); if (opt==1) a[pos]++; if (opt==2) b[pos]++; if (opt==3) c[pos]++,c[pos+1]++; } getsum(a); getsum(b); getsum(b); getsum(c); getsum(c); getsum(c); for (int i=1;i<=n;i++) printf("%d ",(a[i]+b[i]+c[i])%MOD); printf(" "); } return 0; }
题意:给出一个一维行数组和一维列数组相加得到的矩阵,一开始从(0,0)往下走或者往右走,走到(x,y)遇到的询问是:从(0,0)到(x,y)的矩阵中的数前k小的是哪些?
解法:一边走一边用multiset保存行列数,遇到询问则用优先队列暴力模拟前k大(就是从最小行+最小列然后慢慢往大方面扩展),因为题目说了查询总和不大于10^5所以时间是可以接受的。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,tt,a[N],b[N]; typedef multiset<int>::iterator iter; multiset<int> r,c; struct dat{ iter rt,ct; bool operator < (const dat &rhs) const { return (*rt)+(*ct)>*(rhs.rt)+*(rhs.ct); } }; priority_queue<dat> q; int main() { cin>>n>>m>>tt; for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int j=1;j<=m;j++) scanf("%d",&b[j]); int nr=1,nc=1; r.insert(b[1]); c.insert(a[1]); for (int T=1;T<=tt;T++) { char opt[3]; int t; scanf("%s%d",opt,&t); if (opt[0]=='Q') { while (!q.empty()) q.pop(); dat tmp,sav; tmp.rt=r.begin(); tmp.ct=c.begin(); q.push(tmp); for (int i=1;i<=t;i++) { sav=q.top(); q.pop(); printf("%d",*(sav.rt)+*(sav.ct)); if (i<t) printf(" "); else printf(" "); tmp=sav; if (++tmp.rt!=r.end()) q.push(tmp); tmp=sav; if (tmp.rt==r.begin()) if (++tmp.ct!=c.end()) q.push(tmp); } } else { if (opt[0]=='R') { for (int i=nr+1;i<=min(m,nr+t);i++) r.insert(b[i]); nr=min(m,nr+t); } else { for (int j=nc+1;j<=min(n,nc+t);j++) c.insert(a[j]); nc=min(n,nc+t); } } } return 0; }