TIME_LIMIT_EXCEEDED: Codeforces 686D - c++

i was trying to solve this problem on codeforces http://codeforces.com/contest/686/problem/D, but i got TLE. could you tell me what takes so much time in my solution? is it data structures that i use or is the algorithm inefficient? how can i improve it?
#include <iostream>
#include <vector>
using namespace std;
int assignweights(int index, int weights[], vector<vector<int> > &v){
if(v[index].size()==0){
return 0;
}else{
vector<int> children=v[index];
int result=0;
result+=children.size();
for(int i=0; i<children.size(); ++i){
result+=assignweights(children[i], weights, v);
}
weights[index]=result;
}
return weights[index];
}
void getcentroid(int index, vector<vector<int> > &v, int weights[], int & result, int n){
vector<int> children=v[index];
bool b=false;
for(int i=0; i<children.size(); ++i){
if(weights[children[i]]+1>n/2){
if(!result)getcentroid(children[i], v, weights, result, n);
else break;
b=true;
}
}
if(!b){
result=index+1;
}
}
int main(){
int n, q;
cin>>n>>q;
vector<vector<int> > v;
for(int i=0; i<n; ++i){
vector<int> vv;
v.push_back(vv);
}
for(int i=1; i<=n-1; ++i){
int a;
cin>>a;
v[a-1].push_back(i);
}
int weights[n];
for(int i=0; i<n; ++i){
weights[i]=0;
}
assignweights(0, weights, v);
for(int i=0; i<q; ++i){
int index;
cin>>index;
index--;
int result=0;
getcentroid(index, v, weights, result, weights[index]);
cout<<result<<endl;
}
return 0;
}

In the worse test case, your solution my have complexity of O(n*q).
I think the best solution for this problem is for each node of the tree, you create a vector of its descendants at index 1,2,4,...2^x upon it.
With that vector, for each query, it takes O(log(n)) to find the answer.

Related

merge overlapping sub-intervals

I actually tried this question in some different way
#include"bits/stdc++.h"
using namespace std;
vector<vector<int> > overlap(vector<vector<int> > arr,int n){
deque<int> q;
q.push_back(arr[0][0]);
q.push_back(arr[0][1]);
int i=1;
while(i<n){
int j=0;
if(q.back()>arr[i+1][j]){
if(q.back()<arr[i+1][j+1]){
q.pop_back();
q.push_back(arr[i+1][j+1]);
}
}
else{
q.push_back(arr[i+1][j]);
q.push_back(arr[i+1][j+1]);
}
i++;
}
vector<vector<int> > out(n,vector<int>(n,0));
int k=0;
while(!q.empty()){
int l=0;
out[k][l]=q.front();
q.pop_front();
out[k][l+1]=q.front();
q.pop_front();
k++;
}
return out;
}
but while running it isn't showing any output. Is there something wrong in my code or my approach is wrong

Memory issue implementing quick sort

I am trying to implement quick sort to sort a sequence of integers.
I am getting a segmentation default with the following code:
I implemented partition and quick sort recursive calls.But for some c++ reason I am getting an access to memory or an infinite loop I cant understand why.
#include <fstream>
#include<vector>
#include<iostream>
using namespace std;
int pivotSelection(vector<int> A){
return 0;
}
int partition(vector<int> &A,int l,int r){
int i=l+1;
int p = A[l];
for(int j=0; j< A.size(); j++) {
if(A[j]<p){
swap(A[j], A[i] );
i=i+1;
}
}
swap(A[l], A[i-1]);
return i;
}
vector<int> readArray(char* file){
ifstream inFile;
vector<int> A;
inFile.open(file);
int x;
while (inFile >>x ) {
A.push_back(x);
}
return A;
}
void quickSort(vector<int> &A, int l,int r){
if(r==1) {
return ;
}
if(r>l){
int p= partition(A,l,r);
quickSort(A,l,p-1);
quickSort(A,p+1,r);
}
}
int main(){
vector<int> A;//= readArray((char*)"/home/brunoeducsantos/AlgorithmFoundation/quicksort/data.txt");
A.push_back(3);
A.push_back(5);
A.push_back(7);
A.push_back(1);
int length = A.size();
quickSort(A,0,length-1);
for(int i=0;i<length;i++) cout<<A[i]<<endl;
return 0;
};
The expected result is: 1 3 5 7
Fixes noted in comments:
int partition(vector<int> &A,int l,int r){
int i=l+1;
int p = A[l];
for(int j=i; j<=r; j++) { // fix
if(A[j]<p){
swap(A[j], A[i] );
i=i+1;
}
}
swap(A[l], A[i-1]);
return i-1; // fix
}

how to pass dynamic 2d array to a function without using the pointers?

I tried this but it is not working !
can any one help me please this is very important :(
#include <iostream>
using namespace std;
int a[100][100];
void read(int a[][100],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cin>>a[i][j];
}
int main ()
{
int n;
cin>>n;
int a[n][n];
read(a,n);
}
The unclear syntax to pass array by reference is:
void read(int (&a)[100][100], int n)
resulting in
#include <iostream>
void read(int (&a)[100][100], int n)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
std::cin >> a[i][j];
}
int main ()
{
int n;
std::cin >> n;
int a[100][100];
read(a, n);
}
but you might prefer std::vector:
#include <iostream>
#include <vector>
void read(std::vector<std::vector<int>> &mat)
{
for (auto& v : mat) {
for (auto& e : v) {
std::cin >> e;
}
}
}
int main ()
{
int n;
std::cin >> n;
std::vector<std::vector<int>> mat(n, std::vector<int>(n));
read(mat);
}
Since this is tagged C++. I'd like to suggest usage of std::vector. It's dynamic container which is very useful. You can resize it, clear it fill it with ease. Once you understand it's basic usage, they would come really handy in your future C++ development. I modified your code slightly:
#include <iostream>
#include <vector>
using namespace std;
void read(vector<vector<int> >& arr,int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cin>>arr[i][j];
}
int main ()
{
int N;
cin>>N;
vector<vector<int> > arr(N, vector<int>(N));
read(arr, N);
}
They have many advantages over the primitive arrays like they can be initialized easily, suppose you want to initialize all to zero :
vector<vector<int> > arr(N, vector<int>(N, 0));
You don't have to worry about adding the array size whenever passing in functions. vector can easily handle this:
for(i = 0; i < arr.size(); i++) {
for(j = 0; j < arr[i].size(); j++) {
// do stuff
}
}
Moreover with the added methods of the Standard template library like fill, swap. Many operations can be handled easily.

C++ void reverse function

We are converting base 10 to a number in a different base(B). I am having trouble with the void reverse function it will not reverse the order of the numbers.
string convertToBaseB(int num, int b){
int digit;
stringstream answer;
string x="";
while(num>0){
digit=num%b;
num/=b;
answer<<digit;
}
return answer.str();}
void reverse(int x[],int size){//reversing the
for(int k=0; k<size/2; k++){
int temp=x[k];
x[k]=x[size-k-1];
x[size-k-1]=temp;}
}
Your reverse function works fine. However it doesn't looks like C++ to me... In C++ I would have a vector and do:
std::vector<int> arr;
//... fill arr
std::swap_ranges(&arr[0], &arr[arr.size()/2], arr.rbegin());
If you want to stick with your for loop, at least use std::swap like this
void reverse(int x[],int size) {
for(int k=0; k<size/2; k++)
std::swap(x[k], x[size-k-1]);
}
Works for me:
#include <iostream>
using namespace std;
void reverse(int x[],int size)
{
for(int k=0; k<size/2; k++)
{
int temp=x[k];
x[k]=x[size-k-1];
x[size-k-1]=temp;
}
}
int main()
{
const int sz = 9;
int* digits;
digits = new int[sz];
for (int i=0; i < sz; ++i)
{
digits[i] = i;
}
reverse(digits, sz);
for (int i=0; i < sz; ++i)
{
cout<<digits[i]<<" ";
}
cout<<endl;
}

c++ function that fills array

What I'm trying to do:
User inputs two numbers.
Array is declared using those numbers as dimensions.
Function outside main() is filling the array.
Array is accessed in main() for further thingies.
What I have problem with:
Function + array combination doesn't seem to work as I think.
What I did:
void tablica1(int h, int w)
{
int m,n;
for(m=0; m<h; m++)
for(n=0; n<w; n++)
{
arr[h][w]=1;
}
}
What happens:
array arr is inaccessible in tablica1() because it has not been declared in that function.
Of course, when I declare the array in tablica1() it becomes inaccessible in main().
Possible solutions:
Passing arr to tablica1() as a reference - no idea how to do that
Declaring arr in tablica1() and somehow passing it to main() - no idea how to do that
Other possible solutions?
You can declare the array outside of both, at compilation unit level:
int arr[10][10];
void func() {
for (int i=0; i<10; i++) {
for (int j=0; j<10; j++) {
arr[i][j] = i + j;
}
}
}
int main(int argc, const char *argv[]) {
func();
std::cout << arr[3][4] << "\n"; // Output will be 7
return 0;
}
If you want handle a dynamically-sized matrix the most common pattern is to use an std::vector of std::vectors (it's a little more general and therefore a little less efficient than a 2d matrix because each row can have a different length, but in most cases the cost difference is not a big issue)
#include <vector>
std::vector< std::vector< int > > arr;
void func() {
int height = arr.size();
int width = arr[0].size();
for (int i=0; i<height; i++) {
for (int j=0; j<width; j++) {
arr[i][j] = i + j;
}
}
}
int main() {
int height = 13;
int width = 7;
arr = std::vector< std::vector<int> >(height, std::vector<int>(width));
func();
...
}
the two solutions you mentioned
1、Passing arr to tablica1() as a reference
void tablica1(int h, int w,int **arr)
{
int m,n;
for(m=0; m<h; m++)
for(n=0; n<w; n++)
{
arr[h][w]=1;
}
}
void main()
{
const int h=100,w=100;
int arr[h][w];
tablica1(h,w,arr);
}
2、Declaring arr in tablica1() and somehow passing it to main()
int **tablica1(int h, int w)
{
int m,n;
int **arr=new int*[h];
for(int i=0;i<h;i++)
{
arr[i]=new int[w];
}
//it is best to initialize arr by setting each element 0
for(m=0; m<h; m++)
for(n=0; n<w; n++)
{
arr[h][w]=1;
}
return arr;
}
void main()
{
const int h=100,w=100;
int **arr=tablica1(h,w);
//do somting
//delete arr
for(int i=0;i<h;i++)
{
delete []arr[i];
}
delete []arr;
}
If you want to declare a dynamic multidimensional array you can do that with the template give below.
#include<iostream.
#include <vector>
using namespace std;
typedef vector<int> vi;
vector<vi> arr; // arr is a dynamic two dimensional array.
vi.assign(10,vi());//10 rows of type vi .
If you want to enter values in arr you can do that by
vi[0].push_back(a);
vi[0].push_back(b); // a,b,c are some example values..
vi[1].push_back(c);
You can understand using this code
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
typedef vector <int> vi;
vector<vi> arr;// dynamic multidimensional array
int main(){
cout<<"enter array size\n";
int h,w,temp;;
cin>>h>>w;
arr.assign(h,vi());
int i, j;
for(i=0; i < h ;i++)
for(j=0; j < w; j++)
{
cin>>temp;
arr[i].push_back(temp);
}
// for printing
for(i=0; i < h ;i++){
for(j=0; j < w; j++)
{
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}