Tuesday, 23 August 2016
Friday, 10 June 2016
Just Update and Print the array(sqrt decompossion) (update array m time each time index will be ax+b where x= start from 1 to some value k such than ax+b<=n) and print array
Just Update and Print the array
|
You are given a 1-indexed array of size N. Initially, all elements of the array are zeros. You need to performU updates to the array.
Each Update asks you to add 1 to the elements of the array at the indices specified by 'ax+b' for all non-negative integers x, where a and b are positive integers which specify an update query.
After performing all the updates to the array, print the array with every entry separated by space.
Input
First Line of the input contains 2 space separated integers N, U.
Each of the next U lines contains 2 space-separated integers: a and b, specifying an update.
Output
Output the array in a single line after all updates.
Constraints
- 1 ≤ N ≤ 105
- 1 ≤ a, b ≤ N
- 1 ≤ U ≤ 2*105
Example
Input: 7 4 1 3 7 7 7 3 2 2 Output: 0 1 2 2 1 2 2
Explanation
Array after first update : [0,0,1,1,1,1,1]
Array after second update : [0,0,1,1,1,1,2]
Array after third update : [0,0,2,1,1,1,2]
Array after fourth update : [0,1,2,2,1,2,2]
Array after second update : [0,0,1,1,1,1,2]
Array after third update : [0,0,2,1,1,1,2]
Array after fourth update : [0,1,2,2,1,2,2]
=====================================EDITORIAL=========================================
DIFFICULTY:
Medium
PREREQUISITES:
sqrt decomposition, offline range sums
PROBLEM:
Given an array [A1,…,AN] , all initially zeros. You need to perform U updates to the array, where each update asks you to increment the array at the indices ax+b for all integers x≥0 . What is the resulting array?
QUICK EXPLANATION:
Perform all updates where a>U√ manually. Store all other updates (i.e. those with a≤U√ ).
Let's fix an a≤U√ and perform all updates with this a simultaneously. To do so:
- Compute
[C1,…,CN] , whereCi is the number of updates(a,b) withb=i . - Compute
[D1,…,DN] whereDi=Ci+Di−a fori>a andDi=Ci fori≤a . - Finally, increment
Ai withDi for alli .
EXPLANATION:
Obviously, brute-force will not work because the worst case complexity of each update is O(N) , so the overall worst-case running time becomes O(UN) .
The problem is a lot easier though if the updates all have a=1 . In that case, we're only dealing with range sum updates, which are famously easy to solve with a segment tree. In fact, we don't need a segment tree at all! A much simpler algorithm exists for the offline version of the problem, where it is assumed that all updates are known beforehand:
- Compute
[C1,…,CN] , whereCi is the number of updates(1,b) withb=i . This can be done with a linear scan among all updates(1,b) . - Compute
[D1,…,DN] , whereDi is the amount to increment toAi .Di is easily seen to beC1+C2+C3+⋯+Ci , soDi can easily be calculated using the recurrenceDi=Ci+Di−1 fori≥1 with base caseDi=0 fori<1 . - Finally, increment
Ai withDi for alli .
For example, suppose N=11 and we want to process the queries (1,2) , (1,5) , (1,6) , (1,8) , (1,8) and (1,10) . We will have:
One can check that Di is indeed the value to be added to Ai for all i , and that Di=Ci+Di−1 for i≥1 .
Now, what about the updates a>1 ? Well, we don't know yet. But, we can in fact use a similar algorithm as above for the case a=2 : there are two types of updates of the form (2,b) — those with even b and and odd b — and we can use the algorithm above separately for the even and odd ones. And in fact, we can combine both the even and odd half into a single unified algorithm: Just replace the recurrence Di=Ci+Di−1 with Di=Ci+Di−2 . The running time is still O(N) overall.
Actually, we can perform a similar algorithm for all the other a s! Each particular a takes O(N) to process. So we now have an alternative algorithm: group the updates (a,b) according to a , then perform the algorithm above for every a . Unfortunately, this algorithm is also slow. Each time we perform the algorithm above we incur a running time of O(N) , giving an overall running time of O(U+N2) , which is still too slow.
But what if we only perform the algorithm above for some a s? For updates with other a s, we can simply perform the update manually. Let's say we perform the algorithm above only for small a , i.e. those that are ≤s for some (still unknown) value s . Since we perform the algorithm above only s times, and the running time of all other updates is at worst O(N/s) , this gives us an overall running time of O(UN/s+Ns) . If we choose s as, say, Θ(N−−√) , then the overall algorithm becomes O((U+N)N−−√) , which is fast enough to pass the time limit!
Keep in mind though that you have a choice of constant in the "Θ notation" so practically it's still up to you to choose s really. The optimal constant depends on your implementation and you can try to find it via trial-and-error / ternary search. We suggest choosing s not too far from N−−√ though.
Theoretically better parameter
Notice above that we chose s as Θ(N−−√) without really thinking about it that much. It's just pure intuition. Here we'll choose a better parameter to get a theoretically better running time.
The running time is O(UN/s+Ns) , and we want to make the running time as small as possible. Since UN/s decreases and Ns decreases as s increases, it's best to choose s that will make them equal to make their sum as small as possible (at least in terms of O notation). Thus, we want UN/s=Ns . Thus, in fact the better choice would be s=Θ(U√) , NOT Θ(N−−√) , and the running time we get O(U+NU√) . Note that this running time is better than O((U+N)U√) in almost all cases!
Note that we said O(U+NU√) and not just O(NU√) , because it's possible that U>N2 , in which case iterating through all updates dominates the running time.
This doesn't really matter that much in terms of the contest, but it's interesting nonetheless.
Time Complexity:
=======================================CODE===========================================
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> p;
#define getcx getchar_unlocked
inline void inp( int &n )//fast input function
{
n=0;
int ch=getcx();int sign=1;
while( ch < '0' || ch > '9' ){if(ch=='-')sign=-1; ch=getcx();}
while( ch >= '0' && ch <= '9' )
n = (n<<3)+(n<<1) + ch-'0', ch=getcx();
n=n*sign;
}
int ans[100005],n,u;
p arr[200005];
void update2(int st,int ct)
{
int i,x;
int a=arr[st].first;
for(i=0;i<ct;i++,st++)
{
int b=arr[st].second;
for(x=0;a*x+b<=n;x++)
{
ans[a*x+b]++;
}
}
}
void update1(int st,int ct)
{
int i,j;
// creating C[] and D[] array as mentioned in editoral..
int c[n+1];
int d[n+1];
int a=arr[st].first;
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
for(i=st;i<st+ct;i++)
{
c[arr[i].second]++;
}
for(i=1;i<=a;i++)
d[i]=c[i];
for(;i<=n;i++)
d[i]=c[i]+d[i-a];
for(i=1;i<=n;i++)// updating
ans[i]+=d[i];
}
int main()
{
ios_base::sync_with_stdio(false);
int i,j,k;
inp(n);inp(u);
for(i=0;i<u;i++)
{
inp(arr[i].first);
inp(arr[i].second);
}
sort(arr,arr+u);
i=0;
int sq=int(sqrt(n));
while(i<u)
{
int count=1;
while(arr[i].first==arr[i+1].first)
{
count++;
i++;
}
int tempa=arr[i].first;
if(tempa<=sq)
update1(i-count+1,count);
else
update2(i-count+1,count);
i++;
}
for(i=1;i<=n;i++)
cout<<ans[i]<<" ";
}
Subscribe to:
Posts (Atom)