Friday, 15 May 2015

B. Ping-Pong (Easy Version)
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
In this problem at each moment you have a set of intervals. You can move from interval (a, b) from our set to interval (c, d) from our set if and only if c < a < d or c < b < d. Also there is a path from interval I1 from our set to interval I2 from our set if there is a sequence of successive moves starting from I1 so that we can reach I2.
Your program should handle the queries of the following two types:
  1. "1 x y(x < y) — add the new interval (x, y) to the set of intervals. The length of the new interval is guaranteed to be strictly greater than all the previous intervals.
  2. "2 a b(a ≠ b) — answer the question: is there a path from a-th (one-based) added interval to b-th (one-based) added interval?
Answer all the queries. Note, that initially you have an empty set of intervals.
Input
The first line of the input contains integer n denoting the number of queries, (1 ≤ n ≤ 100). Each of the following lines contains a query as described above. All numbers in the input are integers and don't exceed 109 by their absolute value.
It's guaranteed that all queries are correct.
Output
For each query of the second type print "YES" or "NO" on a separate line depending on the answer.
Sample test(s)
input
5
1 1 5
1 5 11
2 1 2
1 2 9
2 1 2
output
NO
YES
Though the language of the question might sound uneasy. It asks simply if we can go from interval (a,b)  to (c,d). The condition of travelling from (a,b) to (c,d) is if c<a<d or c<b<d.
Remeber if we can travel from (a,b) to (c,d) that doesnot necessarily mean we can travel from (c,d) to (a,b) . An example of such a case is if(a,b) entirely lies in the interval (c,d).
Now the question is divided into two parts
(1) adding an interval 
Here eaceh interval is represented as a node. Like (1,5) is node 1 , (5,11) is node 2.
We push (a,b) to vector and check throughout the vector if (a,b) lies between any interval already present in the set of intervals. If present we add a directed edge between interval (a,b) to (c,d). We also check if we can travel from (c,d) to (a,b) [if((intervals[i].ff>a && intervals[i].ff<b )||(intervals[i].ss>a && intervals[i].ss<b))] . If we can also travel from (c,d) to (a,b) then we add a directed edge between (c,d) to (a,b).
(2) Second part is the query part where we do a simple DFS/BFS traversal from the given interval(represented as node) to the second interval . If reachable we print YES else we print NO.
The code is as follows

    *** code begins here**
#include<iostream>
#include<stdio.h>
#include<vector>
#include<list>
#include<queue>
#include<set>
#include<stack>
#define ff first
#define ss second
using namespace std;
int visited[1000];
vector<pair<int ,int > >intervals;
list<int> arr[1000];
int top=0;

void add(int a , int b)
{
 intervals.push_back(make_pair(a,b));
 int l=intervals.size();
 for(int i=0;i<l;i++)
 {
  if((a>intervals[i].ff && a<intervals[i].ss) || (b>intervals[i].ff && b<intervals[i].ss))
  {
   arr[l].push_back(i+1);
   //cout<<"pushing "<<i+1 <<" to  "<<l<<endl;
  }
  if((intervals[i].ff>a && intervals[i].ff<b )||(intervals[i].ss>a && intervals[i].ss<b))
  {
   arr[i+1].push_back(l);
   //cout<<"pushing "<<l <<" to  "<<i+1<<endl;
  }
 }
 
}
void query(int a , int b)
{
     for(int i=1;i<=100+5;i++)
     {
      visited[i]=0;
     }
   stack<long long int> s;
   s.push(a);
   visited[a]=1;
   while(!s.empty())
   {
             int node=s.top();
             if(node==b)
             {
              cout<<"YES"<<endl;
              return ;
             }
    s.pop();
    list<int>::iterator it;
    for(it=arr[node].begin();it!=arr[node].end();it++)
    {
           if(visited[*it]==0)
           {
        s.push(*it);
        visited[*it]=1;
           }
    }
            // step++;          
   } cout<<"NO"<<endl;
}
int main()
{
   int n;
   cin>>n;
   int a ,b,c;
   for(int i=1;i<=n;i++)
   {
       cin>>a>>b>>c;
       if(a==1)
       {
        add(b,c);
       }
       else
       {
        query(b,c);
       }
   } 
}
     *** code ends her**

Tuesday, 12 May 2015

D. Subway
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
A subway scheme, classic for all Berland cities is represented by a set of n stations connected by n passages, each of which connects exactly two stations and does not pass through any others. Besides, in the classic scheme one can get from any station to any other one along the passages. The passages can be used to move in both directions. Between each pair of stations there is no more than one passage.
Berland mathematicians have recently proved a theorem that states that any classic scheme has a ringroad. There can be only one ringroad. In other words, in any classic scheme one can find the only scheme consisting of stations (where any two neighbouring ones are linked by a passage) and this cycle doesn't contain any station more than once.
This invention had a powerful social impact as now the stations could be compared according to their distance from the ringroad. For example, a citizen could say "I live in three passages from the ringroad" and another one could reply "you loser, I live in one passage from the ringroad". The Internet soon got filled with applications that promised to count the distance from the station to the ringroad (send a text message to a short number...).
The Berland government decided to put an end to these disturbances and start to control the situation. You are requested to write a program that can determine the remoteness from the ringroad for each station by the city subway scheme.
Input
The first line contains an integer n (3 ≤ n ≤ 3000), n is the number of stations (and trains at the same time) in the subway scheme. Then n lines contain descriptions of the trains, one per line. Each line contains a pair of integers xi, yi (1 ≤ xi, yi ≤ n) and represents the presence of a passage from station xi to station yi. The stations are numbered from 1 to n in an arbitrary order. It is guaranteed thatxi ≠ yi and that no pair of stations contain more than one passage. The passages can be used to travel both ways. It is guaranteed that the given description represents a classic subway scheme.
Output
Print n numbers. Separate the numbers by spaces, the i-th one should be equal to the distance of the i-th station from the ringroad. For the ringroad stations print number 0.
Sample test(s)
input
4
1 3
4 3
4 2
1 2
output
0 0 0 0 
input
6
1 2
3 4
6 4
2 3
1 3
3 5
output
0 0 0 1 1 2 

DISCUSSION ON THE IMPLEMENTATION
 The question asks us to find a the nodes in the circle in the given graph and then find the distance of all other nodes from the nodes present in the circle.
This question can be divided in two steps
(1) finding the circle 
As the numnber of circle in only 1. an O(n) dfs yields the nodes in the circle.
Starting with any node, we call dfs and mark the visited node as 2(attention we need three states of visited array 0,1 and 2 , 0 for an unvisited node, 1 for a node not a part of circle and 2 for a node that is going to be revisited 2wice.) We see if visited[i]==0 we mark the parent for the node and call dfs recursively for its children. If any time visited[root]=2 is called , we know that this node is being revisited. so we backtrack from the present parent of the revisited node to the node itself through its parent array to mark the fact that these nodes form a circle.
An important observation is to set the visted[node] to 1 after all the pending calls are done.(That means the node is no more to be considered).

Step 2
It is simple BFS (it is preferable we start from a node of the ring), 
The condition for pushing it is if(d[visiting node]>d[parent]+1) then update the distance and revisit the node. If the node is in the circle simply set it to 0.


           ***** The code is *******
#include<iostream>
#include<stdio.h>
#include<queue>
#include<stack>
#include<list>
using namespace std;
list<int> arr[3010];
int visited[3020];
int cycles[3020];
int dist[3020];
int parent[3020];
void distance(int root)
{
dist[root]=0;
queue<int> q;
q.push(root);
   int node;
   while(!q.empty())
   {
    node=q.front();
   // cout<<"node "<<node<< endl;
    q.pop();
    list<int>:: iterator it;
    {
      for(it=arr[node].begin();it!=arr[node].end();it++)
      {
         if(dist[*it]>dist[node]+1)
        {
          if(cycles[*it]==1)
          dist[*it]=0;
 else
 dist[*it]=1+dist[node];
        q.push(*it);
        }
      }
    }
   }
}
void dfs(int root , int par)
{
if(visited[root]==0)
{
visited[root]=2;
parent[root]=par;
list<int> ::iterator it;
for(it=arr[root].begin();it!=arr[root].end();it++)
{
if(*it!=par)
{
dfs(*it,root);
}
}
visited[root]=1;}
if(visited[root]==2)
{
// cout<<"here "<<root<<endl;
int node=par;
while(node!=root)
{
// cout<<"node   "<<node<<endl;
cycles[node]=1;
node=parent[node];
}
cycles[root]=1;
}
}
void fill(int filler[],int val, int lim)
{
for(int i=0;i<=lim+2;i++)
{
filler[i]=val;
}
}
int main()
{
int n;
cin>>n;
int a,b;
for(int i=1;i<=n;i++)
{
cin>>a>>b;
arr[a].push_back(b);
arr[b].push_back(a);
}
fill(visited,0,n+2);
fill(dist,1000000,n+2);
fill(cycles,-1,n+2);
fill(parent,0,n+2);
dfs(1,-1);
// cout<<"Exiting "<<endl;
for(int i=1;i<=n;i++)
{
if(cycles[i]==1)
{  
// cout<<"bfs call using "<<i<<endl;
distance(i);
break;
}
}
for(int i=1;i<=n;i++)
{
cout<<dist[i]<<" ";
}
cout<<endl;
return 0;
}
   **** The code ends here****

Tuesday, 5 May 2015

1017. Staircases

Time limit: 1.0 second
Memory limit: 64 MB
One curious child has a set of N little bricks (5 ≤ N ≤ 500). From these bricks he builds different staircases. Staircase consists of steps of different sizes in a strictly descending order. It is not allowed for staircase to have steps equal sizes. Every staircase consists of at least two steps and each step contains at least one brick. Picture gives examples of staircase forN=11 and N=5:
Problem illustration
Your task is to write a program that reads the number N and writes the only number Q — amount of different staircases that can be built from exactly N bricks.

Input

Number N

Output

Number Q

Sample

inputoutput
212
995645335


concept

This program involves dynamic programming as can be easily manifested .
Implemented using recursion . The state of the memoised arrar is dp[bricks used in previous state][brick remaining ] . We try to build the staircase with the remaining bricks. It is evident that if the remaining number of bricks is less than or equal to the number of bricks used in  previous state, then the possible ways is 0. If remaining ==0 the there is 1 way.(that is only n bricks in a single step).
The code is as follows 

#include<iostream>
#include<stdio.h>
using namespace std;
long long int dp[507][507];
long long int solve(int prev, int rem)
{
// cout<<"calling "<<prev<<" "<<rem<<endl;
if(rem==0)
return 1;
if(rem<=prev)
return 0;
if(dp[prev][rem]!=-1)
return dp[prev][rem];
long long int val=0;
for(int i=prev+1;i<=rem;i++)
{
val+=solve(i,rem-i);
}
dp[prev][rem]=val;
return dp[prev][rem];
}
int main()
{
for(int i=0;i<=502;i++)
{
for(int j=0;j<=502;j++)
dp[i][j]=-1;
}
int n;
cin>>n;
long long int val=0;
val=solve(0,n);
//cout<<dp[1][4]<<endl;
cout<<val-1<<endl;
}

/* code ends here */

We print val-1 as the position of the nth being lying in a single column needs to be subtracted as according to the question statement minimum number of steps is 2.