The following is the implementation of http://www.spoj.pl/problems/LITE/ using Segment Tree's with lazy propagation. I am new to segment trees and I cannot understand why I am getting TLE. Could someone please look at it and help me correct my error?
#include <iostream>
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAX 100000
using namespace std;
int M[2*MAX+1];
int flag[2*MAX+1];
int count;
void refresh(int begin,int end,int n)
{
M[n] = end-begin+1 - M[n];
flag[n]=0;
flag[n*2] =!flag[n*2];
flag[n*2+1] =!flag[n*2+1];
}
void update(int begin,int end,int i,int j,int n=1)
{
if(flag[n])
{
refresh(begin,end,n);
}
if(begin>=i && end<=j)
{
if(!flag[n])
{
refresh(begin,end,n);
}
flag[n] = 0;
return;
}
else if(begin>=end)
{
return;
}
else
{
int mid = (begin+end)>>1;
if(i<=mid)
{
update(begin,mid,i,j,n*2);
}
if(j>mid)
{
update(mid+1,end,i,j,n*2+1);
}
if(flag[2*n])
{
refresh(begin,mid,2*n);
}
if(flag[2*n+1])
{
refresh(mid+1,end,2*n+1);
}
M[n] = M[n*2]+ M[n*2+1];
}
}
int query(int begin,int end,int i,int j,int n=1)
{
if(flag[n])
{
refresh(begin,end,n);
}
if(begin>=i && end<=j)
{
return M[n];
}
if(begin>=end)
{
return 0;
}
int mid = (begin+end)>>1;
int l=0,r=0;
if(i<=mid)
{
l = query(begin,mid,i,j,n*2);
}
if(j>mid)
{
r = query(mid+1,end,i,j,n*2+1);
}
if(flag[2*n])
{
refresh(begin,mid,2*n);
}
if(flag[2*n+1])
{
refresh(mid+1,end,2*n+1);
}
M[n] = M[n*2]+ M[n*2+1];
return l+r;
}
int main()
{
memset(M,0,sizeof M);
int n,m,a,b,c;
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
if(a==0)
{
update(1,n,b,c);
}
else
{
printf("%d\n",query(1,n,b,c));
}
}
return 0;
}
M[node]^=1; might be faster than M[node] = (M[node]==0)?1:0;, and (begin+end)>>1 faster than (begin/end)/2, but not very relevant
LE: Try if making the recursive functions inline will run faster. I think it unravels the recursion a couple of times and works a little bit faster. Maybe sending the parameters as references will make it run faster, try that out. If the test cases are chosen properly you still shouldn't be able to pass the tests with this trickery, but it helps sometimes.
Related
This is the logic I came up with, but I am getting SIGSEGV error. and I don't know why it is happening.
#include <bits/stdc++.h>
using namespace std;
int path(int m, int n,int dist[1000][1000]) {
if(dist[m][n]!=-1) {
return dist[m][n];
}
else if(m==1 && n==1) {
return 1;
}
else if(m==0 || n==0) {
return 0;
}
dist[m][n]=path(m-1,n,dist)+path(m,n-1,dist);
return dist[m][n];
}
int main() {
// your code goes here
int dist[1000][1000];
memset(dist, -1, sizeof(dist)*1000*1000);
int s=path(3,3,dist);
return 0;
}
What should be changed in the below code? It shows the following error
ERROR: ld.so: object '/home/bot/funcs.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
Error in `/home/bot/dcb7b4b8f54571a4467c2113b7856878': free(): invalid next size (fast): 0x0000000000c350b0
#include <iostream>
using namespace std;
int merge(int *left,int nl,int *right,int nr,int *a)
{
int i=0,j=0,k=0;
while(i<nl && j<nr)
{
if(left[i]<right[j])
{
a[k]=left[i];
i++;
}
else
{
a[k]=right[j];
j++;
}
k++;
}
while(i<nl)
{
a[k]=left[i];
i++;
}
while(j<nr)
{
a[k]=right[j];
j++;
}
}
int mergesort(int *a,int n)
{
if(n<2) return 0;
int mid=n/2;
int *left=new int[mid];
int *right=new int[n-mid];
for(int i=0;i<=mid-1;i++)
{
left[i]=a[i];
}
for(int i=mid;i<=n-1;i++)
{
right[i]=a[i];
}
mergesort(left,mid);
mergesort(right,n-mid);
merge(left,mid,right,n-mid,a);
delete[]left;
delete[]right;
}
int main() {
//code
int a[]={10,7,8,9,4,2,3,6,5,1};
int n=sizeof(a)/sizeof(a[0]);
mergesort(a,n);
for(int i=0;i<10;i++)
{
cout<<a[i]<<"\t";
}
return 0;
}
Fixes noted in comments, seems to be working now. A one time allocation of a temp array either in main or in a helper function would be faster. Using mutually recursive functions (one merges AtoA, the other merges AtoTemp, they call each other), eliminates having to copy data. I can post an example later if wanted. Bottom up merge sort would be slightly faster.
#include <iostream>
using namespace std;
// fix return type to void
void merge(int *left,int nl,int *right,int nr,int *a)
{
int i=0,j=0,k=0;
while(i<nl && j<nr)
{
if(left[i]<right[j])
{
a[k]=left[i];
i++;
}
else
{
a[k]=right[j];
j++;
}
k++;
}
while(i<nl)
{
a[k]=left[i];
i++;
k++; // fix
}
while(j<nr)
{
a[k]=right[j];
j++;
k++; // fix
}
}
// fix return type to void
void mergesort(int *a,int n)
{
if(n<2) return; // fix: change return type to void
int mid=n/2;
int *left=new int[mid];
int *right=new int[n-mid];
for(int i=0;i<=mid-1;i++)
{
left[i]=a[i];
}
for(int i=mid;i<=n-1;i++)
{
right[i-mid]=a[i]; // fix
}
mergesort(left,mid);
mergesort(right,n-mid);
merge(left,mid,right,n-mid,a);
delete[]left;
delete[]right;
}
int main() {
//code
int a[]={10,7,8,9,4,2,3,6,5,1};
int n=sizeof(a)/sizeof(a[0]);
mergesort(a,n);
for(int i=0;i<10;i++)
{
cout<<a[i]<<"\t";
}
cout << endl; // added this not needed
return 0;
}
Cleanup, changed output to not use tabs:
#include <iostream>
#include <iomanip> // for std::setw()
using namespace std;
void merge(int *left,int nl,int *right,int nr,int *a)
{
int i=0,j=0,k=0;
while(i<nl && j<nr)
{
if(left[i]<right[j])
a[k++]=left[i++];
else
a[k++]=right[j++];
}
while(i<nl)
a[k++]=left[i++];
while(j<nr)
a[k++]=right[j++];
}
void mergesort(int *a,int n)
{
if(n<2)
return;
int mid=n/2;
int *left=new int[mid];
int *right=new int[n-mid];
for(int i=0;i<=mid-1;i++)
left[i]=a[i];
for(int i=mid;i<=n-1;i++)
right[i-mid]=a[i];
mergesort(left,mid);
mergesort(right,n-mid);
merge(left,mid,right,n-mid,a);
delete[]left;
delete[]right;
}
int main() {
int a[]={10,7,8,9,4,2,3,6,5,1};
int n=sizeof(a)/sizeof(a[0]);
mergesort(a,n);
for(int i=0;i<10;i++)
cout<<setw(2)<<a[i]<<" "; // 2 digit field output
cout << endl;
return 0;
}
You should use std::vector instead of raw pointer:
typedef std::vector<int> ivector;
void merge( const ivector &l, const ivector &r, ivector &to )
{
ivector_const::iterator il = l.begin();
ivector_const::iterator ir = r.begin();
ivector::iterator ito = to.begin();
while( true ) {
if( il == l.end() ) {
if( ir == r.end() )
return;
*ito++ = *ir++;
} else {
if( ir == r.end() || *il < *ir )
*ito++ = *il++;
else
*ito++ = *ir++;
}
}
}
void mergesort( ivector &v )
{
if(v.size()<2) return;
ivector::iterator imid = v.begin() + v.size() / 2;
ivector left( v.begin(), imid );
ivector right( imid, v.end() );
mergesort(left);
mergesort(right);
merge( left, right, v );
}
int main() {
//code
ivector a ={10,7,8,9,4,2,3,6,5,1};
mergesort(a);
for(size_t i=0;i<a.size();i++)
{
cout<<a[i]<<"\t";
}
return 0;
}
Note: I did not validate your algorithm just rewrote it with std::vector instead of raw pointer. You can notice how simpler your function become when you use proper data type.
can someone give me tricky test example that crash my code. Task --> http://www.spoj.com/problems/SHOP/
I can't find any mistake in my code so I am asking your help.
Code:
http://pastebin.com/6wuFWWJH
#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
struct koord
{
int x;
int y;
koord(int _x=0,int _y=0)
{
x=_x;
y=_y;
}
};
queue<koord>Q;
bool bio[150][150];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int dist[150][150];
char polje[150][150];
int a,b;
void bfs(int a1,int b1)
{
Q.push(koord(a1,b1));
bio[a1][b1]=true;
while(!Q.empty())
{
koord pos=Q.front();
Q.pop();
for(int i=0;i<4;++i)
{
koord dalje=koord(pos.x+dx[i],pos.y+dy[i]);
if(dalje.x>=0 && dalje.x<b && dalje.y>=0 && dalje.y<a)
{
if(polje[dalje.x][dalje.y]!='X' || polje[dalje.x][dalje.y]!='S')
if(bio[dalje.x][dalje.y]==false)
{
if(polje[dalje.x][dalje.y]=='D')
{
bio[dalje.x][dalje.y]=true;
dist[dalje.x][dalje.y]=dist[pos.x][pos.y];
Q.push(dalje);
}
else
{
bio[dalje.x][dalje.y]=true;
dist[dalje.x][dalje.y]=dist[pos.x][pos.y]+(polje[dalje.x][dalje.y]-'0');
Q.push(dalje);
}
}
if(polje[dalje.x][dalje.y]=='D' && dist[dalje.x][dalje.y]>dist[pos.x][pos.y])
{
dist[dalje.x][dalje.y]=dist[pos.x][pos.y];
Q.push(dalje);
}
else if(dist[dalje.x][dalje.y]>dist[pos.x][pos.y]+(polje[dalje.x][dalje.y]-'0'))
{
dist[dalje.x][dalje.y]=dist[pos.x][pos.y]+(polje[dalje.x][dalje.y]-'0');
Q.push(dalje);
}
}
}
}
}
int main()
{
scanf("%d%d",&a,&b);
while(a!=0 && b!=0)
{
int c=0,d=0,e=0,f=0;
for(int i=0;i<b;++i)scanf("%s",polje[i]);
//scanf("\n");
for(int i=0;i<b;++i)
for(int j=0;j<a;++j)
{
if(polje[i][j]=='S'){c=i;d=j;}
if(polje[i][j]=='D'){e=i;f=j;}
}
bfs(c,d);
printf("%d\n",dist[e][f]);
for(int i=0;i<150;++i)
for(int j=0;j<150;++j){bio[i][j]=false;dist[i][j]=0;}
Q.empty();
scanf("%d%d",&a,&b);
}
return 0;
}
I try some weird test example like :
3 3
S9D
1X1
111
But my program print 5, and that is good. So I need your help.
Mistake was here:
if(polje[dalje.x][dalje.y]!='X' || polje[dalje.x][dalje.y]!='S')
It should be
if(polje[dalje.x][dalje.y]!='X' && polje[dalje.x][dalje.y]!='S')
The code and output is working fine before backtracking but I am not able to proceed for backtracking. What to do do after unplacing? It is giving the output of first 4 queens only means before backtracking.
#include <iostream>
#include <conio.h>
using namespace std;
int recu(int i,int k);
void place(int i,int k);
void unplace(int i,int k);
int q[8][8];
int row[8];
int column[8];
int c[15];
int d[15];
int totalqueens=0;
int s;
int main()
{
for(int i=0;i<8;i++) //Flags for rows,columns and diagonals
{
row[i]=0;
column[i]=0;
c[i]=0;d[i]=0;
}
for(int i=8;i<15;i++)
{
c[i]=0;d[i]=0;
}
int i=0;
int k=0;
recu(i,k);
for(int i=0;i<8;i++)
{
for(int k=0;k<8;k++)
{
if(q[i][k]==1)
{
cout<<"(";
cout<<i;
cout<<",";
cout<<k;
cout<<")";
}
}
}
getch();
return 0;
}
int recu(int i,int k)
{
if(totalqueens==8)
{ goto print; }
if(k<8)
{
if(column[i]==0 && row[k]==0 && c[i+k]==0 && d[i-k+7]==0)
{
place(i,k);
s=k;
k=0;
recu(i+1,k);
}
else
{
recu(i,k+1);
unplace(i-1,s);
//**I am not able to proceed further**
}
}
print:
;
}
void place(int i,int k)
{
totalqueens++;
q[i][k]=1;
row[k]=1;
column[i]=1;
c[i+k]=1;
d[i-k+7]=1;
}
void unplace(int i,int k)
{
q[i][k]=0;
row[i]=0;
column[k]=0;
c[i+k]=0;
d[i-k+7]=0;
//cout<<"before call";
recu(i,k+1);
//cout<<"working";
}
Your code only gives out one solution.
u r not put the output part in the right place.
try like this:
void print()
{
for(int i=0;i<8;i++)
{
for(int k=0;k<8;k++)
{
if(q[i][k]==1)
{
cout<<"(";
cout<<i;
cout<<",";
cout<<k;
cout<<")";
}
}
}
}
make that to be one method. and then, in your recu method, modify to:
if(totalqueens==8)
{
print();
return;
}
Keep in mind that DO NOT use goto sentence. It is very ugly and may cause unknown problems.
You backtrack when not all queens have been placed and you cannot place another queen. You backtrack as follows:
See if the last placed queen can be placed in a later spot. If so, place it there and stop backtracking. (Resume placing.)
Remove the last placed queen.
If there are no queens left, stop. All solutions have been found.
Go to step 1.
why my program Time Limited Error?
because of the sort?
this is the question
link text
#include <cstdio>
#include <cstring>
using namespace std;
int map[22][44];
int book[22];
int total;
int sum;
int way[22];
int tails[22];
int tail;
void init()
{
memset(map,0,sizeof(map));
memset(book,0,sizeof(book));
sum =0;
memset(way,0,sizeof(way));
way[1]=1;
memset(tails,0,sizeof(tails));
}
void sort()
{
int t;
for (int i=1;i<=22;i++)
{
if (tails[i]==0)
break;
else
{
for (int j=1;j<=tails[i]-1;j++)
for (int k=j+1;k<=tails[i];k++)
{
if (map[i][j] > map[i][k])
{
t = map[i][j];
map[i][j]=map[i][k];
map[i][k]=t;
}
}
}
}
}
void dfs(int x,int y)
{
if ((x < 1)||(x > 22))
return;
if (book[x]==1)
return;
//printf("%d \n",x);
if (x == total)
{
sum++;
for (int i=1;i<=y-1;i++)
{
printf("%d ",way[i]);
}
printf("%d",total);
printf("\n");
return;
}
tail = tails[x];
for (int i=1;i<=43;i++)
{
book[x]=1;
way[y]=x;
dfs(map[x][i],y+1);
book[x]=0;
}
}
int main()
{
int temp1,temp2;
//freopen("ex.in","r",stdin);
//freopen("ex.out","w",stdout);
int c = 0;
while(scanf("%d",&total)!=EOF)
{
c++;
printf("CASE ");
printf("%d",c);
printf(":");
printf("\n");
init();
for (;;)
{
scanf("%d%d",&temp1,&temp2);
if ((temp1 == 0)&&(temp2 == 0))
break;
else
{
tails[temp1]++;
tail = tails[temp1];
map[temp1][tail]=temp2;
tails[temp2]++;
tail = tails[temp2];
map[temp2][tail]=temp1;
}
}
sort();
dfs(1,1);
printf("There are ");printf("%d",sum);printf(" routes from the firestation to streetcorner ");printf("%d",total);printf(".");
printf("\n");
}
return 0;
}
Because your sorting algoritm is in worst-case O(n*n), you can use InnoSort for better worst-case complexity O(n*log(n)).
You are using C++ then use sort function from <algorithm> header to do this simplest.
Documentation you can find at http://www.sgi.com/tech/stl/sort.html
For a start, you're accessing tails and map past the end. C++ arrays are zero-indexed, so the first element is 0, and the last valid elements are tails[21] and map[21][43].