TLE in SPOJ ACTIV - c++

I am trying out SPOJ ACTIV. (http://www.spoj.com/problems/ACTIV/) My algorithm works in n log n but still time limit exceeded is coming. Could someone help me please.
We are supposed to find the number of non-empty non-overlapping subsets of activities a person can do in intervals marked (start,end). I am first sorting by start time. Then im doing a binary search on the end in the rest of the array while maintaining the sum in a sum variable(dp)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
using namespace std;
typedef pair<long long,long long> p;
vector<long long> ans;
vector<long long> cuml_sum;
int comp(p a,p b){
return a.first<b.first;
}
long long mod(long long sum,long long powe){
return (sum-(sum/powe)*powe);
}
int bins(vector<p> arr,long long start,long long end,long long search){
if(start>end)
return start;
int mid = (start+end)/2;
if(arr[mid].first==search)
return mid;
else if(arr[mid].first<search)
return bins(arr,mid+1,end,search);
else
return bins(arr,start,mid-1,search);
}
void reverse(string s){
int i=0;
int j=s.length()-1;
while(j>=0){
cout<<s[j];
j--;
}
}
void process(long long num)
{
string s="";
int i=0;
while(i<8){
s+=num%10+'0';
num/=10;
if(num==0){
while(i<7){
s+='0';
i++;
}
break;
}
i++;
}
reverse(s);
cout<<"\n";
}
long long func(vector<p> arr)
{
int n=arr.size();
ans[n-1]=1;
long long sum=ans[n-1];
cuml_sum[n-1]=ans[n-1];
for(int i=n-2;i>=0;i--){
int j=bins(arr,i+1,n-1,arr[i].second);
if(j>n-1)
{
ans[j]=0;
cuml_sum[j]=0;
}
ans[i]=1+cuml_sum[j];
cuml_sum[i]=ans[i]+cuml_sum[i+1];
sum+=ans[i];
}
return mod(sum,(long long)pow(10,8));
}
int main(void){
vector<p> arr;
int test,n;
for(int i=0;i<100000;i++){
ans.push_back(0);
cuml_sum.push_back(0);
}
long long a,b;
while(1){
cin>>n;
if(n==-1)
return 0;
for(int i=0;i<n;i++){
cin>>a>>b;
arr.push_back(p(a,b));
}
sort(arr.begin(),arr.end(),comp);
process(func(arr));
arr.clear();
}
return 0;
}

Related

I need help regarding weird time limit exceeded error in cpp

So there was this code which got accepted when i took its output in a vector
#include <iostream>
#include<vector>
using namespace std;
int main(){
int t; cin >> t;
while(t--){
vector<int>v;
int n,k; cin >> n >> k;
for(int i=0;i<n;i++){
int x; cin >> x;
if(x%k==0) v.push_back(1);
else v.push_back(0);
}
for(auto x:v) cout <<x <<"";
cout << endl;
}
return 0;
}
but then there is this code gives Time Limit Exceeded error when i am direct printing it
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
int main()
{
int t;
cin>>t;
while(t--)
{
ll k,d;
int n,i;
cin>>n>>k;
for(i=0;i<n;i++)
{
cin>>d;
if(d%k==0)
cout<<"1";
else
cout<<"0";
}
cout<<"\n";
}
}
Can you tell why ?
(The contest is now over)Here is the question in case
Edit:1 I used int instead of long long as well as printf as well as cin.tie(NULL) stuff , but still to no avail
The implementation with the cout in the for loop body is going to bottle-beck on the cout output for sure, especially given a modulo operation is very cheap in contrast.
See below question as reference:
C++: Does cout statement makes code slower
Something like this would work better:
#include <bits/stdc++.h>
#include <vector>
using namespace std;
#define ll long long int
int main()
{
int t;
cin>>t;
while(t--)
{
ll k,d;
int n,i;
cin>>n>>k;
std::vector<bool> r(n);
for(i=0;i<n;i++)
{
cin>>d;
if(d%k==0)
r[i] = true;
}
for(auto i : r)
cout<<(i ? '1' : '0')<<endl;
cout<<"\n";
}
}

Why is recursive solution faster than an iterative solution for this case?

I am trying to obtain a solution for this question https://www.spoj.com/problems/COINS/.
But oddly enough, my iterative solution:
#include <iostream>
using namespace std;
int main() {
int n;
while(cin >> n){
long long int dp[n+2];
dp[0]=0;
for(long long int i=1; i<=n; i++)
dp[i]=max(dp[i/2]+dp[i/3]+dp[i/4], i);
cout << dp[n] <<endl;
}
return 0;
}
gets a TLE, while the recursive solution for this(Not mine) gets accepted in no time:
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
map<int, long long> dp;
long long f(int n){
if(n==0) return 0;
if(dp[n]!=0) return dp[n];
long long aux=f(n/2)+f(n/3)+f(n/4);
if(aux>n) dp[n]=aux;
else dp[n]=n;
return dp[n];
}
int main(){
int n;
while(scanf("%d",&n)==1) printf("%lld\n",f(n));
return 0;
}
Shouldn't it be the opposite? I am genuinely confused.
The iterative solution is linear in n i.e it's O(n) while the recursive one is O(log_2 n ) from what I can understand.

Declaring 2-dimensional array in "Edit distance" on spoj locally gives runtime error?

While solving http://www.spoj.com/problems/EDIST/ , when I declare the 2-d array globally: (http://ideone.com/jG3jPW)
#include <iostream>
using namespace std;
long long int s[2001][2001];
int main() {
int t;
string a,b;
long long int i,j;
for(i=0;i<2001;i++)
{
s[i][0]=i;
s[0][i]=i;
}
cin>>t;
while(t>0)
{
cin>>a>>b;
t--;
for(i=1;i<=a.length();i++)
{
for(j=1;j<=b.length();j++)
{
if(a[i-1] == b[j-1])
s[i][j]=s[i-1][j-1];
else
s[i][j] = min(min(s[i-1][j],s[i-1][j-1]),s[i][j-1]) + 1;
}
}
cout<<s[i-1][j-1]<<"\n";
}
return 0;
}
no error occurs. But when i declare the same array locally(http://ideone.com/Tyj6UU),
#include <iostream>
using namespace std;
int main() {
int t;
string a,b;
long long int i,j;
long long int s[2001][2001]; //declared locally
for(i=0;i<2001;i++)
{
s[i][0]=i;
s[0][i]=i;
}
cin>>t;
while(t>0)
{
cin>>a>>b;
t--;
for(i=1;i<=a.length();i++)
{
for(j=1;j<=b.length();j++)
{
if(a[i-1] == b[j-1])
s[i][j]=s[i-1][j-1];
else
s[i][j] = min(min(s[i-1][j],s[i-1][j-1]),s[i][j-1]) + 1;
}
}
cout<<s[i-1][j-1]<<"\n";
}
return 0;
}
runtime error occurs. Why?
It seems that you are having some kind of problem with memory allocation.
In your second approach (i.e., the one with local declaration), change:
long long int s[2001][2001];
To:
long long int ** s = new long long int * [2001];
for (i=0;i<2001;i++)
s[i] = new long long int[2001];
This will solve your problem.

Unexpected output of c++ program

I was solving http://codeforces.com/problemset/problem/552/B.
In my first attempt I came up with something like:
#include <bits/stdc++.h>
using namespace std;
int digit(long a){
int i=0;
while(a){
a/=10;
i++;
}
return i;
}
int main()
{
long n;
long long s=0;
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n;
int dig=digit(n),i=0;
while(i<dig){
s+=(n-pow(10,i)+1);
i++;
}
cout<<s;
return 0;
}
But for input
1000000
My program outputed
5888895
I was expecting
5888896
In my second try I wrote pow function for myself:
#include <bits/stdc++.h>
using namespace std;
int digit(long a){
int i=0;
while(a){
a/=10;
i++;
}
return i;
}
long long pow1(int a){
long long s=1;
while(a--){
s*=10;
}
return s;
}
int main()
{
long n;
long long s=0;
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n;
int dig=digit(n),i=0;
while(i<dig){
long long aux=pow1(i);
s+=(n-aux+1);
i++;
}
cout<<s;
return 0;
}
And this time it was correct.How can one explain the working behind it?
The problem with the built-in pow function is that is does not work as accurate as your function. pow calculates x to the y as exp(y*log(x)). This generic formula works with all (even non-integral) exponents, and its performance is (mostly) independent on the arguments. The problem with that formula is, that pow(10,2) might be 99.9, which gets truncated to 99 when it is converted to an integer type. Try pow(10,i) + 0.5 to perform proper rounding.
You may not need pow here. This works as expected and is faster too.
#include <iostream>
typedef unsigned long long ull;
using namespace std;
ull count(ull n) {
ull i = 0;
for (; n; ++i) n /= 10;
return i;
}
int main() {
ull n;
cin >> n;
ull digits = count(n);
ull ans = digits * (n + 1);
for (ull i = 0, j = 1; i < digits; ++i, j *= 10)
ans -= j;
cout << ans;
return 0;
}
All testcases passed on codeforces.com
You just need to multiply pow(10,i-1) with 0.1. That will do the work you needed.
#include <iostream>
#include <cmath>
using namespace std;
int digit_calc(long long num);
long long digit_counter(long long num, int digit);
int main()
{
long long num,digit,total;
cin>>num;
digit=digit_calc(num);
total=digit_counter(num, digit);
cout<<total<<endl;
return 0;
}
int digit_calc(long long num){
int digit=0;
while(num){
digit++;
num=num/10;
}
return digit;
}
long long digit_counter(long long num, int digit){
long long sup,net,total=0;
while(num){
sup=0.1*(pow(10,digit)-1);
net=num-sup;
total=total+(net*digit);
num=sup;
digit--;
}
return total;
}
It passed all test cases on codeforce.

spoj prime conjecture PRIMEZUK

I am trying to solve the question http://www.spoj.com/problems/PRIMEZUK/
#include<iostream>
#include<cstdio>
#include<math.h>
#define l long long
using namespace std;
l chk(l a)
{
for(int i=2;i<=sqrt(a);++i)
{
if(a%i==0)
{
return a/i;
}
}
return 0;
}
main()
{
// freopen("in.txt","r",stdin);
int t,n,a;
l prod=1,flag;
//t=inp();
cin>>t;
for(int j=1;j<=t;++j)
{
cin>>n;
//n=inp();
if(n==0)
prod=-1;
else
prod=1;
while(n--)
{
cin>>a;
//a=inp();
prod*=a;
}
++prod;
flag=chk(prod);
if(!flag)
printf("Case #%d: %lld\n",j,prod);
else
printf("Case #%d: %lld\n",j,flag);
}
}
i am getting right answer for the sample test case but whne i submit i am getting wrong answer...any hints???
You are getting wrong answer because "return a/i" may also return a non-prime number.So you should check whether "return a/i" is prime or not..
Try This...
#include<bits/stdc++.h>
long long int check(long long int a)//Function to check whether a number is prime or not
{
long long int i,k;
k=sqrt(a);
for(i=2;i<=k;++i)
{
if(a%i==0) // if not prime
return check(a/i); //then find greatest prime
}
return a;
}
int main()
{
int j=1,t;
long long int n,a,prod,flag;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
if(n==0)
prod=-1;
else
prod=1;
while(n--)
{
scanf("%lld",&a);
prod*=a;
}
++prod;
printf("Case #%d: %lld\n",j,check(prod));
j++;
}
return 0;
}