Tuesday, 30 July 2013

Domino Principle

http://codeforces.com/problemset/problem/56/E

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Vasya is interested in arranging dominoes. He is fed up with common dominoes and he uses the dominoes of different heights. He put n dominoes on the table along one axis, going from left to right. Every domino stands perpendicular to that axis so that the axis passes through the center of its base. The i-th domino has the coordinate xi and the height hi. Now Vasya wants to learn for every domino, how many dominoes will fall if he pushes it to the right. Help him do that.
Consider that a domino falls if it is touched strictly above the base. In other words, the fall of the domino with the initial coordinate x and height h leads to the fall of all dominoes on the segment [x + 1, x + h - 1].
Input
The first line contains integer n (1 ≤ n ≤ 105) which is the number of dominoes. Then follow n lines containing two integers xi and hi ( - 108 ≤ xi ≤ 108, 2 ≤ hi ≤ 108) each, which are the coordinate and height of every domino. No two dominoes stand on one point.
Output
Print n space-separated numbers zi — the number of dominoes that will fall if Vasya pushes the i-th domino to the right (including the domino itself).
Sample test(s)
Input
4
16 5
20 5
10 10
18 2
Output
3 1 4 1 
Input
4
0 10
1 5
9 10
15 10
Output
4 1 2 1 
 
Code:
 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct node{
    int x,y,p;
}a[maxn];
int n;
int f[maxn],ans[maxn];
bool cmp(node i,node j)
{
    return i.x<j.x;
}
int main()
{
    int i,x,y;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
    scanf("%d%d",&x,&y);
    a[i].x=x;a[i].y=x+y-1;
    a[i].p=i;
    }
    sort(a+1,a+n+1,cmp);
    for(i=n;i>=1;i--){
    f[i]=1;
    for(int j=i+1;j<=n;j+=f[j]){
        if (a[i].y>=a[j].x) f[i]+=f[j];
        else break;
    }
    ans[a[i].p]=f[i];
    }
    for(i=1;i<=n;i++) printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

Corporation Mail

http://codeforces.com/problemset/problem/56/C

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The Beroil corporation structure is hierarchical, that is it can be represented as a tree. Let's examine the presentation of this structure as follows:
  • employee ::= name. | name:employee1,employee2, ... ,employeek.
  • name ::= name of an employee
That is, the description of each employee consists of his name, a colon (:), the descriptions of all his subordinates separated by commas, and, finally, a dot. If an employee has no subordinates, then the colon is not present in his description.
For example, line MIKE:MAX.,ARTEM:MIKE..,DMITRY:DMITRY.,DMITRY... is the correct way of recording the structure of a corporation where the director MIKE has subordinates MAX, ARTEM and DMITRY. ARTEM has a subordinate whose name is MIKE, just as the name of his boss and two subordinates of DMITRY are called DMITRY, just like himself.
In the Beroil corporation every employee can only correspond with his subordinates, at that the subordinates are not necessarily direct. Let's call an uncomfortable situation the situation when a person whose name is s writes a letter to another person whose name is also s. In the example given above are two such pairs: a pair involving MIKE, and two pairs for DMITRY (a pair for each of his subordinates).
Your task is by the given structure of the corporation to find the number of uncomfortable pairs in it.
Input
The first and single line contains the corporation structure which is a string of length from 1 to 1000 characters. It is guaranteed that the description is correct. Every name is a string consisting of capital Latin letters from 1 to 10 symbols in length.
Output
Print a single number — the number of uncomfortable situations in the company.
Sample test(s)
Input
MIKE:MAX.,ARTEM:MIKE..,DMITRY:DMITRY.,DMITRY...
Output
3
Input
A:A..
Output
1
Input
A:C:C:C:C.....
Output
6

Code:
#include<iostream>
using namespace std;
    char a;
    int n,res;
    string s[1001];
int main()
{
    while(cin>>a)
    {
 if(a=='.')
 {
     for(int i=0;i<n;i++)
  if(s[i]==s[n])
      res=res+1;
     s[n]="";
     n--;
 }
 else
 {
     if(a==':')
  n=n+1;
     else
     {
  if(a==',')
      n++;
  else
      s[n]+=a;
     }
 }
    }
    cout<<res<<endl;
    return 0;
} 
 

Spoilt Permutation

http://codeforces.com/problemset/problem/56/B

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Vasya collects coins: he has exactly one coin for every year from 1 to n. Naturally, Vasya keeps all the coins in his collection in the order in which they were released. Once Vasya's younger brother made a change — he took all the coins whose release year dated from l to r inclusively and put them in the reverse order. That is, he took a certain segment [l, r] and reversed it. At that the segment's endpoints did not coincide. For example, if n = 8, then initially Vasya's coins were kept in the order 1 2 3 4 5 6 7 8. If Vasya's younger brother chose the segment [2, 6], then after the reversal the coin order will change to 1 6 5 4 3 2 7 8. Vasya suspects that someone else could have spoilt the permutation after his brother. Help him to find that out. Check if the given permutation can be obtained from the permutation 1 2 ... n using exactly one segment reversal. If it is possible, find the segment itself.
Input
The first line contains an integer n (1 ≤ n ≤ 1000) which is the number of coins in Vasya's collection. The second line contains space-separated n integers which are the spoilt sequence of coins. It is guaranteed that the given sequence is a permutation, i.e. it contains only integers from 1 to n, and every number is used exactly 1 time.
Output
If it is impossible to obtain the given permutation from the original one in exactly one action, print 0 0. Otherwise, print two numbers l r (1 ≤ l < r ≤ n) which are the endpoints of the segment that needs to be reversed to obtain from permutation 1 2 ... n the given one.
Sample test(s)
Input
8
1 6 5 4 3 2 7 8
Output
2 6
Input
4
2 3 4 1
Output
0 0
Input
4
1 2 3 4
Output
0 0
 
Code:
 #include<iostream>
using namespace std;
int main()
{
    int x,y,n,a[1001];
    cin>>n;
    for(int i=0;i<n;i++)
    {
 cin>>a[i];
    }
    x=0;
    y=n-1;
    while(a[x]==x+1)
    {
 x++;
    }
    while(a[y]==y+1)
    {
 y--;
    }
    if(x>y)
    {
 cout<<"0 0\n";
    }
    else
    {
 for(int i=x;i<=y;i++)
 {
     if(a[i]!=y+x+1-i)
     {
  cout<<"0 0\n";
  return 0;
     }
 }
 cout<<x+1<<" "<<y+1<<endl;
    }
    return 0;
}

A. Bar

memory limit per test
256 megabytes
input
standard input
output
standard output
According to Berland laws it is only allowed to sell alcohol to people not younger than 18 years. Vasya's job is to monitor the law's enforcement. Tonight he entered a bar and saw n people sitting there. For every one of them Vasya happened to determine either the age or the drink the person is having. Vasya can check any person, i.e. learn his age and the drink he is having at the same time. What minimal number of people should Vasya check additionally to make sure that there are no clients under 18 having alcohol drinks?
The list of all alcohol drinks in Berland is: ABSINTH, BEER, BRANDY, CHAMPAGNE, GIN, RUM, SAKE, TEQUILA, VODKA, WHISKEY, WINE
Input
The first line contains an integer n (1 ≤ n ≤ 100) which is the number of the bar's clients. Then follow n lines, each describing one visitor. A line either contains his age (an integer from 0 to 1000) or his drink (a string of capital Latin letters from 1 to 100 in length). It is guaranteed that the input data does not contain spaces and other unnecessary separators.
Only the drinks from the list given above should be considered alcohol.
Output
Print a single number which is the number of people Vasya should check to guarantee the law enforcement.
Sample test(s)
Input
5
18
VODKA
COKE
19
17
Output
2
Note
In the sample test the second and fifth clients should be checked.

Code:
a=["ABSINTH", "BEER", "BRANDY", "CHAMPAGNE", "GIN", "RUM", "SAKE", "TEQUILA", "VODKA", "WHISKEY", "WINE"]
x=input()
n=0
for i in range(x):
    y=raw_input()
    if y in a:
    n=n+1
    else:
    j=0;
    for i in y:
        if (i<'0'or i>'9'):
        j=1
    if j==0:
        if(int(y)<18):
        n=n+1
print n

 

Tuesday, 16 July 2013

The Probability Of Winning

Refer:
http://www.codechef.com/problems/PROB

Proof:
assumption:p(t1,t2,t3)=t1/(t1+t2)
There are two parts to the proof .
1. Coins of type 3 don't matter .
2. Initial draw doesn't matter .

You can prove both the claims by mathematical induction
Proof 1 :
p(t1,t2,t3) = t1/(t1+t2+t3) + t3 / ( t1+t2+t3) * p(t1,t2,t3-1) . ( Statement 1 )
By induction hypothesis ,
p(t1,t2,t3-1) = t1/(t1+t2) .
which proves Statement 1 gives us assumed formula

Proof 2 :
p(t1,t2,t3,t4) = t1/(t1+t2+t3) * p(t1-1,t2,t3,t4-1) + t2/(t1+t2+t3) * p(t1,t2-1,t3,t4-1) + t3/(t1+t2+t3) * p(t1,t2,t3-1,t4-1) . (statement 2)
By induction hypothesis ,
p(t1-1,t2,t3,t4-1) = (t1-1)/(t1-1+t2)
p(t1,t2-1,t3,t4-1) = (t1)/(t1+t2-1)
p(t1,t2,t3-1,t4-1) = (t1)/(t1+t2)
which proves statement 2 gives us assumed formula.

alternative solution:
the logic is split in two parts:
  1. t4 has no significance : Note that these tickets are removed randomly, so in some cases the prob of winning will increase and in others it will decrease. Overall, it will have no effect. I was satisfied with this intuition.
  2. t3 has no significance : I actually worked this out mathematically. Let r denote the total number of tickets then we can get,
    P[win] = (t1/r)(1 + t3/(r-1) + t3 (t3-1)/((r-1)(r-2)) + ...
    P[loss] = (t2/r)(1 + t3/(r-1) + t3 (t3-1)/((r-1)(r-2)) + ...
Note that the big multiplicative term is same in both and can be replaced by L.
Also P[win] + P[loss] = 1
So, we have
P[win] + P[loss] = (t1/r + t2/r) * L
1 = (t1/r + t2/r) * L
L = r/(t1 + t2)
We can substitute this value of L back in P[win],
P[win] = (t1/r)* (r/(t1+t2))
P[win] = t1 / (t1+t2)

Program:
#include<stdio.h>
#include<math.h>

int main(){
    long long t,a,b,c,d;
 double ans;
 scanf("%lld",&t);
 while(t--){
  scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
  ans = a/(double)(a+b);
  ans = round(ans*10000000)/10000000;
  printf("%0.7f\n",ans);
 }
 return 0;
}


 

Monday, 15 July 2013

Chef and Walking on the rectangle

 
Solution:
/*Chef and Walking on the rectangle*/
#include<stdio.h>
int main()
{
    int K,M,N,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d",&N,&M,&K);
        if(((N==1) && (M<=2)) || ((N<=2) && (M==1)))
            printf("0\n");
        else if((N==1) || (M==1))
            printf("%d\n",K);
        else
            printf("%d\n",(K/2)+(K&1));
    }
    return 0;
}

Thursday, 11 July 2013

How to check if a given point lies inside or outside a polygon?

Given a polygon and a point ‘p’, find if ‘p’ lies inside the polygon or not. The points lying on the border are considered inside.
polygon21

Following is a simple idea to check whether a point is inside or outside.
1)Draw a horizontal line to the right of each point and extend it to infinity.
2) Count the number of times a line intersects the polygon. We have:
    even number ---> point is outside
    odd number ----> point is inside
polygon3

If point is same as one of the vertices of polygon, then it intersects with two lines.  We explicitly handle it by comparing the point with n vertices of the polygon.

Following is C++ implementation of the above idea.
// A C++ program to check if a given point lies inside a given polygon
#include <iostream>
#include <limits.h>
using namespace std;
struct Point
{
int x;
int y;
};
// Given three colinear points p, q, r, the function checks if
// point q lies on line segment 'pr'
bool onSegment(Point p, Point q, Point r)
{
if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) &&
q.y <= max(p.y, r.y) && q.y >= min(p.y, r.y))
return true;
return false;
}
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // colinear
return (val > 0)? 1: 2; // clock or counterclock wise
}
// The function that returns true if line segment 'p1q1'
// and 'p2q2' intersect.
bool doIntersect(Point p1, Point q1, Point p2, Point q2)
{
// Find the four orientations needed for general and
// special cases
int o1 = orientation(p1, q1, p2);
int o2 = orientation(p1, q1, q2);
int o3 = orientation(p2, q2, p1);
int o4 = orientation(p2, q2, q1);
// General case
if (o1 != o2 && o3 != o4)
return true;
// Special Cases
// p1, q1 and p2 are colinear and p2 lies on segment p1q1
if (o1 == 0 && onSegment(p1, p2, q1)) return true;
// p1, q1 and p2 are colinear and q2 lies on segment p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) return true;
// p2, q2 and p1 are colinear and p1 lies on segment p2q2
if (o3 == 0 && onSegment(p2, p1, q2)) return true;
// p2, q2 and q1 are colinear and q1 lies on segment p2q2
if (o4 == 0 && onSegment(p2, q1, q2)) return true;
return false; // Doesn't fall in any of the above cases
}
// Returns true if the point p lies inside the polygon[] with n vertices
bool isInside(Point polygon[], int n, Point p)
{
// There must be at least 3 vertices in polygon[]
if (n < 3) return false;
// Create a point for line segment from p to infinite
Point extreme = {INT_MAX, p.y};
// Count intersections of the above line with sides of polygon
int count = 0;
for (int i = 0; i < n-1; i++)
{
// If p is same as one of the vertices
if (p.x == polygon[i].x && p.y == polygon[i].y)
return true;
// Otherwise check for intersection
if (doIntersect(polygon[i], polygon[i+1], p, extreme))
count++;
}
// If p is same as last vertex
if (p.x == polygon[n-1].x && p.y == polygon[n-1].y)
return true;
// Last side (from last to first point) is missed in the
// above loop, consider it now
if (doIntersect(polygon[n-1], polygon[0], p, extreme))
count++;
// Return true if count is odd, false otherwise
return count&1; // Same as (count%2 == 1)
}
// Driver program to test above functions
int main()
{
Point polygon[] = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};
int n = sizeof(polygon)/sizeof(polygon[0]);
Point p = {20, 20};
isInside(polygon, n, p)? cout << "Yes \n": cout << "No \n";
p = {5, 5};
isInside(polygon, n, p)? cout << "Yes \n": cout << "No \n";
return 0;
}
Output:
No
Yes
Time Complexity: O(n) where n is the number of vertices in the given polygon.
Source:
http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf