@Pinetrie
2019-07-29T01:24:18.000000Z
字数 2620
阅读 913
题意:给出n个数,p个询问。每个询问包含数字a、b,要求求出a,a+b,a+2b,……,a+nb的总和。
思路:对于b大于根号n的可以直接暴力,这个复杂度为s*sqrt(n)(s为这种的询问的个数)。对于b小于根号n的,可以先dp预处理出对于一个b的所有a的情况,然后o(1)询问,复杂度为n*sqrt(n)(二维dp会暴空间)。最坏情况时间复杂度为p*sqrt(n)。
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 3 * 100010;ll w[maxn],dp[maxn],ans[maxn];ll n,p,bl;struct Ques{ll a,b,id;}q[maxn];vector<Ques>Q[maxn];int main(){scanf("%lld",&n);bl = sqrt(n);for(int i = 1;i <= n;i++) scanf("%lld",&w[i]);scanf("%lld",&p);for(int i = 1;i <= p;i++){scanf("%lld %lld",&q[i].a,&q[i].b);q[i].id = i;if(q[i].b >= bl){ll sum = 0;ll a = q[i].a,b = q[i].b;for(int i = a;i <= n;i += b) sum += w[i];ans[q[i].id] = sum;}else{Q[q[i].b].push_back(q[i]);}}for(int i = 1;i <= 600;i++){for(int j = n;j >= 1;j--){if(i + j > n) dp[j] = w[j];else dp[j] = dp[i + j] + w[j];}for(int j = 0;j < (int)Q[i].size();j++) ans[Q[i][j].id] = dp[Q[i][j].a];}for(int i = 1;i <= p;i++) printf("%lld\n",ans[i]);return 0;}
题意:给出n个数,q个操作。操作一把l,r区间的所有数加x。操作二询问数组中值等于y的两个数的最大距离,如果没有则输出-1。
思路:把区间分成根号n块,让每个块内的数有序。对于修改操作,被l,r跨过的区间只需要记录一个增加值add[i],代表第i块的整体增量。未被跨过的区间不超过2*sqrt(n),可以直接直接暴力修改。对于查询操作,只需要在每块区间二分查找y值,然后更新最小、最大的下标即可。总的时间复杂度O(nlog√n + q√n * log√n)。
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 5 * 100010;ll n,q,bl;ll add[800],a[maxn],pos[maxn];inline ll block(ll x) {return (x - 1) / bl + 1;}struct NODE{ll w,id;bool operator< (const NODE &rhs) const{return w < rhs.w;}}node[maxn];int main(){scanf("%lld %lld",&n,&q);bl = sqrt(n);for(int i = 1;i <= n;i++){scanf("%lld",&a[i]);node[i].w = a[i];node[i].id = i;}for(int i = 1;i <= block(n);i++){sort(node + (i - 1) * bl + 1,node + min(i * bl,n) + 1);}for(int i = 1;i <= n;i++) pos[node[i].id] = i;while(q--){ll op,l,r,x;scanf("%lld",&op);if(op == 1){scanf("%lld %lld %lld",&l,&r,&x);for(int i = block(l) + 1;i < block(r);i++) add[i] += x;if(block(l) < block(r)){for(int i = l;i <= block(l) * bl;i++) node[pos[i]].w += x;for(int i = (block(r) - 1) * bl + 1;i <= r;i++) node[pos[i]].w += x;sort(node + (block(l) - 1) * bl + 1,node + min(block(l) * bl,n) + 1);sort(node + (block(r) - 1) * bl + 1,node + min(block(r) * bl,n) + 1);for(int i = (block(l) - 1) * bl + 1;i <= block(l) * bl;i++) pos[node[i].id] = i;for(int i = (block(r) - 1) * bl + 1;i <= min(block(r) * bl,n);i++) pos[node[i].id] = i;}else{for(int i = l; i <= r; i++) node[pos[i]].w += x;sort(node + (block(l) - 1) * bl + 1,node + min(block(l) * bl,n) + 1);for(int i = (block(l) - 1) * bl + 1; i <= min(block(l) * bl,n); i++) pos[node[i].id] = i;}}else{struct NODE temp;scanf("%lld",&x);ll minl = maxn,maxr = 0;for(int i = 1;i <= block(n);i++){temp.w = x - add[i];ll pl = lower_bound(node + (i - 1) * bl + 1,min(i * bl,n) + node + 1,temp) - node;ll pr = upper_bound(node + (i - 1) * bl + 1,min(i * bl,n) + node + 1,temp) - node;for(int j = pl;j < pr;j++){minl = min(minl,node[j].id);maxr = max(maxr,node[j].id);}}if(minl == maxn && maxr == 0)printf("-1\n");elseprintf("%lld\n",maxr - minl);}}return 0;}