Friday, November 15, 2013

Knuth Morris Pratt (KMP) Algorithm

Objective:
Given a (smaller) pattern string P, find all its occurrences in a (larger) text string T.

Learning Resources:
http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=stringSearching 

Good Intuition and worked examples:
http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/

Short Explanation:
1) Use the pattern string in order to build the Failure Function array. 
2) Use the failure function to skip certain characters in the text and print each occurrence of the pattern in the text.

Complexity: O(length_of_pattern + length_of_text)

Implementation:
// P - pattern, F - failure function, m - P.size()
void FailureFunction(string &P, vector<int> &F, int m) {
    int i = 1, j = 0;
    F[0] = 0;
    while(i < m) {
        if(P[i] == P[j])
            {F[i] = j+1; i++; j++;}
        else if(j > 0)
            j = F[j-1];
        else
            {F[i] = 0; i++;}
    }
}

// P - pattern, T - text
void KMP(string &P, string &T) {
    int m=P.size(), n=T.size(), i=0, j=0;
    vector<int> F(m+1);
    FailureFunction(P,F,m);
    while(i < n) {
        while(j && T[i] != P[j]) j = F[j-1]; 
        if(T[i] == P[j]) j++;
        if(j == m) printf("%d\n", i-j+1);
        i++;
    }
}

Tuesday, November 12, 2013

CPSIG Week 4: String Algorithms and Range Querying

Learning Material

Basic Track:

String Algorithms:

Regular Expressions:
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=regularExpressions


Knuth Morris Pratt (KMP) Algorithm:
Concept:
http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=stringSearching

Implementation: 
http://machlearner.blogspot.in/2013/11/knuth-morris-pratt-kmp-algorithm.html


Range Querying:

Sparse Table (ST) Algorithm:
http://www.topcoder.com/tc?d1=tutorials&d2=lowestCommonAncestor&module=Static

Segment Tree:
http://www.topcoder.com/tc?d1=tutorials&d2=lowestCommonAncestor&module=Static
http://letuskode.blogspot.in/2013/01/segtrees.html

Binary Indexed Tree:
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees

Advanced Track:

String Algorithms:

Suffix Array: 

O(n*(logn)^2) - Easier to implement in a contest scenario.
Explanation of the Algorithm:
http://discuss.codechef.com/questions/21385/a-tutorial-on-suffix-arrays

Good Examples:
http://www.stanford.edu/class/cs97si/suffix-array.pdf

O(n*logn) - Manber and Myers Algorithm
http://apps.topcoder.com/forums/?module=RevisionHistory&messageID=1171511

O(n) - DC3 Algorithm
http://algo2.iti.kit.edu/documents/jacm05-revised.pdf


A resource where you can find a compilation of resources and problems:
http://qr.ae/GTA78

Practice Problems

Basic Track:

KMP: NHAY, PERIOD, EPALIN, FINDSR, VPALIN
Segment Tree: BRCKTS, LITE, GSS1, GSS3, HORRIBLE, ORDERSET
BIT: INVCNT, MATSUM, YODANESS

Advanced Track:
SARRAY

Thursday, October 24, 2013

ICPC Amritapuri Online Contest 2013 - Editorials

There were 4 problems in total. 3 problems were adhoc in nature. The fourth problem was a tiling problem which my team could not solve during the contest. The problems took some time to load initially (about 5 minutes) but after that the contest went on without any major problems.

The following solutions use my Competitive Programming template which you can find here: http://machlearner.blogspot.in/2013/01/in-competition-programming-where-speed.html

Problem 1: Blurry Vision

Problem Statement:
https://icpc.hackerrank.com/contests/amrita13/challenges/blurry-vision

Solution:
Our objective in this problem is to find whether two sub matrices of a given matrix (which might potentially overlap) are the same. If multiple such sub matrices occur, find the one with maximum number of elements.

We could just iterate through all possible sub matrices, keep adding them to a map (either by converting the sub matrix into a string or a vector<string>). If the current sub matrix already exists in the map, we take answer to be maximum of current answer and number of elements in the current sub matrix.

Code:
map<string,int> m1;
string a[11];

int main()
{
    int t,n,m,ans;
    string s;

    t = ni();

    while(t--) {
        n = ni(); m = ni(); ans = 0;

        REP(i,0,n)
            cin >> a[i];
        REP(i,0,n)
            REP(j,0,m)
                REP(k,i,n)
                    REP(l,j,m) {
                        s = "";
                        REP(p,i,k+1) {
                            REP(q,j,l+1)
                                s.pb(a[p][q]);
                            s.pb('$');
                        }
                        if(m1.find(s) != m1.end())
                            ans = max(ans,m1[s]);
                        else
                            m1[s] = (k-i+1)*(l-j+1);
                    }
        printf("%d\n", ans);
        m1.clear();
    }
        
    return 0;
}


Complexity: O((n*m)^3) per test case.

Problem 2: Flee to Shelter

Problem Statement:
https://icpc.hackerrank.com/contests/amrita13/challenges/flee-to-shelter

Solution:
This was the easiest problem of the contest. Objective of the problem was to find the total time taken to transfer all the instruments.

ans = ceil(n/m)*time_taken_for_one_trip*2

Code:

int main()
{
    int t,n,m,T,ans;

    t = ni();

    while(t--) {
        n = ni(); m = ni(); T = ni();
        if(n%m == 0)
            ans = (n/m)*T*2;
        else
            ans = (n/m+1)*T*2;
        printf("%d\n", ans);
    }
        
    return 0;
}


Complexity: O(1) per test case.

Problem 3: Creating a wormhole

Problem Statement: https://icpc.hackerrank.com/contests/amrita13/challenges/creating-a-wormhole

Solution:
Given an list of edge lengths, our objective is to find the polygon with maximum number of edges which can be formed from the given edges.

We use the generalization of triangle inequality to any polygon  - http://en.wikipedia.org/wiki/Triangle_inequality#Generalization_of_the_inequality_to_any_polygon

First, we sort the array. Then we check for each edge i (0 based index), whether its length is smaller than sum of lengths of all previous edges. If this is true, ans = i+1, else we continue the process. ans is initialized to -1 to account for the case where no such polygon is possible.

Code:
int a[10005];

int main()
{
    int t,n,ans;
    LL sum;

    t = ni();

    while(t--) {
        n = ni(); ans = -1;
        REP(i,0,n)
            a[i] = ni();
        sort(a,a+n);
        sum = a[0] + a[1];
        REP(i,2,n) {
            if(sum > a[i])
                ans = i+1;
            sum += a[i];
        }
        printf("%d\n", ans);
    }
        
    return 0;
}

Complexity: O(n*logn) per test case.

Problem 4: Galaxy Search

Problem Statement:
https://icpc.hackerrank.com/contests/amrita13/challenges/galaxy-search

Solution: (to be updated soon...)

Note: These are just my personal solutions and not an official editorial.

Feel free to leave suggestions or alternate solutions as comments.

Thursday, October 17, 2013

CPSIG Week 3: Basic Data Structures and Graph Theory

Knowledge and usage of Basic Data Structures are the bare minimum skills every Sport Programmer needs to be equipped with. Graph theory is another  important domain which provides an alternate view of problems and facilitates one to reduce these problems into graphs and solve them using classical algorithms. Here some basic topics, learning materials and practice problems are listed to get you started into these topics.

Learning Material
 
Basic Track:

1) C++ STL: Vector, Stack, Queue, List(Linked List), Set, Map, Priority Queue
For reference: http://www.cplusplus.com/reference/stl/ (very useful during coding if you forget something)
Pre-requisite for Graph Algorithms: Representing graphs as adjacency lists, adjacency matrices etc. 

2) Depth First Search
3) Breadth First Search

4) Floyd-Warshall

5) Single Source Shortest Paths - Dijkstra's in O(V^2)

Advanced Track:
1) Single Source Shortest Paths - Dijkstra's in O(V+E*logV) - Refer to priority queue or set approach in Advanced STL uses mentioned above or read this tutorial:
2) Single Source Shortest Paths(with negative weights) - Bellman-Ford:
3) Topological Sorting:

4) Strongly Connected Components - Kosaraju's or Tarjan's algorithm.
A) Kosaraju's:
B) Tarjan's:

5) Bi-Connected Components, finding Articulation Points and Bridges.

6) Minimum Spanning Tree - Prims or Kruskals algorithms.
A) Prims:
Implementation: 
B) Kruskals: 

Practice Problems

Basic Track:

Advanced Track:

Wednesday, October 16, 2013

All Pairs Shortest Paths - Floyd Warshall Algorithm

Learning Resource: http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm

Short Description:
1) This algorithm finds shortest distance been every pair of nodes in a graph.
2) The implementation shared here uses adjacency matrix representation.
3) Complexity of the algorithm is O(n^3)

Working:
1) Initialize all distances between nodes (i,j) to INF (a very large value which is guaranteed to be more than the maximum distance between two nodes - here it is chosen as 10^9) where i != j and 0 where i==j.
2) Input the distances for every node (i,j) and populate the adjacency matrix.
3) Calculate all-pairs shortest paths by iterating for all i,j,k and using the result min-distance(i,j) = min(min-distance(i,j) , min-distance(i,k)+min-distance(k,j))

Implementation:

// Nodes are numbered from 1 to n
for(int i=1; i<=n; i++)
    for(int j=1;j<=n;j++)
        a[i][j]=(i==j)?(0):(1000000000);

// Input a[][] here.

for(int k=1; k<=n; k++)
    for(int i=1; i<=n; i++)
        for(int j=1;j<=n;j++)
            a[i][j]=min(a[i][j],a[i][k]+a[k][j]);

Tuesday, October 15, 2013

Matrix Exponentiation

Learning resource:
Fast exponentiation of numbers: http://machlearner.blogspot.in/2013/09/modular-exponentiation.html

Same concept can be applied to raise matrices to a power.

Implementation:
// If the original matrix is stored in a[][], matexp(n) calculates a^n.

#define DIM 10
#define MOD 1000000007
LL a[DIM][DIM],cpy[DIM][DIM];

void matmultiply(LL y[DIM][DIM])
{
    for(int i=0;i<DIM;i++)
        for(int j=0;j<DIM;j++)
        {
            cpy[i][j]=0;
            for(int r=0;r<DIM;r++)
                cpy[i][j]=(cpy[i][j] + a[i][r]*y[r][j]) % MOD;
        }
    memcpy(a,cpy,sizeof cpy);
}

void matexp(int n)
{
    if(n==1)
        return;
    else if(n%2==0)
    {
        matexp(n/2);
        matmultiply(a);
    }
    else
    {
        LL temp[DIM][DIM];
        memcpy(temp,a,sizeof a);
        matexp(n-1);
        matmultiply(temp);
    }
}

Thursday, October 10, 2013

Chinese Remainder Theorem

Reading:
http://en.wikipedia.org/wiki/Chinese_remainder_theorem

Here i make use of the following computational formula to calculate the solution of a system of simultaneous congruences using  Chinese Remainder Theorem:

x := \sum_{i} a_i \frac{N}{n_i} \left[\left(\frac{N}{n_i}\right)^{-1}\right]_{n_i}

Modular inverse is computed using Extended Euclid's Algorithm.

Implementation:

int egcd(int a, int b, LL &x, LL &y) {
    if(b == 0) {
        x = 1; y = 0; return a;
    }
    int gcd = egcd(b,a%b,y,x);
    y -= a/b*x;
    return gcd;
}

int crt(VI &a, VI &m) {
    int N=1,n=a.size();
    LL t,x,y,ret=0;
    REP(i,0,n) N *= m[i];
    REP(i,0,n) {
        t = N/m[i];
        egcd(t,m[i],x,y);
        ret = (ret + ((a[i]*t)%N)*x)%N;
    }
    if(ret < 0) ret += N;
    return ret;
} 

Tuesday, October 8, 2013

CPSIG Week 2: Dynamic Programming.

Dynamic Programming (DP) is more of a technique than a topic. Your skill in solving DP problems will increase with more and more practice of different types of DP problems. Here i try to mention a list of topics, learning resources and practice problems which should give you a good foundation.  

Learning Material
Basic Track:

Longest Common Subsequence
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/

Longest Increasing Subsequence
In O(n^2) - http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/ (See the second implementation)
In O(n*logn) - http://comeoncodeon.wordpress.com/2009/08/12/longest-increasing-subsequence-lis/

Edit Distance
http://en.wikipedia.org/wiki/Levenshtein_distance

Read the Iterative with full matrix solution first.

Matrix Chain Multiplication
http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/

0/1 Knapsack
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/Dynamic/knapsackdyn.htm

Some more Classical DP Problems: http://people.csail.mit.edu/bdean/6.046/dp/

Solving DP using Matrix Exponentiation

If DP problem can be reduced to a recurrence relation, then use matrix exponentiation to solve the problem.

Solving DP using Bitmasking

Usually these are problems where all possible subsets need to be generated and we need to store information about each subset to avoid re-computation.

Advanced Track:

Reading:
Commonly used DP State Domains - http://apps.topcoder.com/forums/?module=Thread&threadID=697369&start=0


Topics and practice problems:

State Space Reduction
http://www.topcoder.com/stat?c=problem_statement&pm=8605&rd=12012&rm=269199&cr=7581406

Counting

Strategies and Expected values

Solving in reverse - Easier characterization from the end.
http://www.spoj.pl/problems/MUSKET/

DP on Trees

DP with Data Structures

Practice Problems

Basic Track:
AIBOHP, AMZSEQ, KNAPSACK, SAMER08D, ELIS, LIS2, M3TILE, GNY07H, HIST2, MIXTURES, SCUBADIV, DCEPCA06, DCEPC501, EDIST, ACODE

Advanced Track: 
MUSKET, COURIER (more to be updated here...)

Some more problems:
http://codeforces.com/blog/entry/325

http://apps.topcoder.com/forums/;jsessionid=B83B4A412C257FA7F334AD9649D3E766?module=Thread&threadID=674592&start=0&mc=9#1775726

Saturday, September 14, 2013

CPSIG Week 1: Basic Mathematics.

Learning Material:

Basic Track:

Recursion:
Concept and Implementation:
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=recursionPt1
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=recursionPt2
Uses: Too many to list, Highly useful concept. Basic idea of recursion is a Pre-Requisite before coming to the lecture.

Time Complexity:
Concept:
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=complexity1
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=complexity2

Video Tutorials:
http://www.youtube.com/watch?v=OpebHLAf99Y&list=PL2_aWCzGMAwI9HK8YPVBjElbLbI3ufctn
http://www.youtube.com/watch?v=PFd5s0bHgAQ&list=PL2_aWCzGMAwI9HK8YPVBjElbLbI3ufctn

GCD using Euclid's Algorithm:
Sieve of Erastothenes:
Concept and Implementation: http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=math_for_topcoders
Uses: GCD - calculating GCD, LCM. Prime Sieve - Fast calculation of prime numbers in a range.

GCD and Prime Sieve is the minimum you need to learn from this link. Feel free to read the rest too if you have time.

Modular Exponentiation:
Concept: http://en.wikipedia.org/wiki/Modular_exponentiation
Implementation: http://machlearner.blogspot.in/2013/09/modular-exponentiation.html
Uses: Calculating (a^n)%MOD in O(logn) time.

Matrix Exponentiation:
Concept: http://fusharblog.com/solving-linear-recurrence-for-programming-contest/
Implementation: Refer to above link. It is essentially the same as modular exponentiation for numbers, with matrix multiplication instead of normal multiplication. It is highly recommended you implement this on your own and not re-use code.
Uses: Solving Linear Recurrences like Fibonacci numbers in O((d^3)*logn) time where d - dimension of the matrix.

Modular Inverse where MOD is a prime:
Concept: http://en.wikipedia.org/wiki/Modular_multiplicative_inverse
Implementation: http://machlearner.blogspot.in/2013/09/modular-multiplicative-inverse.html
Uses: To calculate nCr%MOD where MOD is prime. nCr = (fact[n]/(fact[r]*fact[n-r]))%MOD = fact[n]%MOD * mod_inv(fact[r]*fact[n-r], MOD)

Advanced Track(for those who have completed all above mentioned concepts):

Primality Testing - Miller Rabbin:
Concept and Implementation: http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=primalityTesting
Uses: To check whether a single number is prime or not.

Inclusion-Exclusion Principle:
Concept: http://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
Implementation:
Uses: To calculate probabilities / solve some counting problems where the concept of inclusion-exclusion is involved.

Chinese Remainder Theorem:
Concept: http://en.wikipedia.org/wiki/Chinese_remainder_theorem
Implementation: http://machlearner.blogspot.in/2013/10/chinese-remainder-theorem.html
Uses:  Determine a number n that when divided by some given divisors leaves given remainders

Euler Totient Function:
Concept: http://en.wikipedia.org/wiki/Euler%27s_totient_function
Implementation:
Uses: Too many to list. Please read the wiki page.

Advanced Counting Techniques - Polya Counting, Burnside's Lemma:
Concept:
http://en.wikipedia.org/wiki/Burnside%27s_lemma
http://petr-mitrichev.blogspot.in/2008/11/burnsides-lemma.html
Implementation:
Uses:

Problemset:

Basic Track:
SEQ, SPP, FIBOSUM, FIBTWIST, PRIME1, PRIMEZUK, DCEPCA06, LASTDIG2, GCD2, KOPC12B, RANGZER2, ZSUM

Advanced Track:
PON, PAGAIN, HNUMBERS, POWPOW, NDIVPHI, SQFREE, ETF, PROOT, NGM2

Modular Multiplicative Inverse

Objective: To calculate modular multiplicative inverse of a number.(Refer to the link if you dont know what this term means)

Solution:
Two possible solutions are very nicely explained in the Wikipedia link. So, i will just share C++ implementations using both the methods

Using Extended Euclid:

void extended_gcd(int a, int b, int &gcd, int &x, int &y)
{
    x=0; y=1; gcd=b;
    int u=1,v=0,m,n,q,r;
    while(a!=0)
    {
        q=gcd/a; r=gcd%a;
        m=x-u*q; n=y-v*q;
        gcd=a; a=r; x=u; y=v; u=m; v=n;
    }
}

LL mod_inv(int a)
{
    int gcd,x,y;
    extended_gcd(a,MOD,gcd,x,y);
    if(gcd==1)
        return (LL)((x+MOD)%MOD);
}
Using Euler's Theorem:

Use modular exponentiation from here

Modular inverse is same as mod_exp(a,MOD-2,MOD).

Modular Exponentiation

Objective: To calculate (a^n)%MOD in O(logn) time, where a,n,MOD are constants.

Solution:
a^n = (a^(n/2) )^2 if n is even
           (a^(n-1))*a is n is odd
 Base cases:
a^1 = a
a^0 = 1

So we can solve this problem by recursion.

Code:

int mod_exp(int a, int n, int MOD) {
    if(n == 0)
        return 1%MOD;
    else if(n == 1)
        return a%MOD;
    else if(n&1)
       return (a*mod_exp(a,n-1,MOD))%MOD;
   else
   {
       int ret = mod_exp(a,n/2,MOD);
       return (ret*ret)%MOD;
   }
}
Note: To take care of overflow issues, it is recommended to use long long instead of int.

Iterative Version:

LL modexp(LL a, int n, LL MOD) {
    if(a == 0) {
        if(n == 0) return 1;
        else return 0;
    }
    LL ret = 1;
    while(n > 0) {
        if(n&1) {
            ret *= a;
            if(ret >= MOD) ret %= MOD;
        }
        n >>= 1;
        a *= a;
        if(a >= MOD) a %= MOD;
    }
    return ret;
}

Sunday, September 8, 2013

Competitive Programming SIG - Introductory Lecture.

This was an introduction to Competition Programming given by me and Romal in BITS Pilani.

The introductory lecture comprised of an introduction to what is Sport Programming, why to do it, how to get better at it and some motivation to why you should try it. Also, we talked about how we are going to handle the Competitive Programming Special Interest Group (CPSIG) lectures over the course of this semester.

Visit the page www.facebook.com/CPSIG for regular updates on this Interest Group.

For those you missed it here are the lecture slides and the motivational video:

Slide

Video:


For more motivation and a story about Gennady Korotkevich (the child prodigy mentioned in the lecture) visit Competition Programming Resources -> Motivational and Advice on this blog.

Friday, January 4, 2013

Topological Sort and Strongly Connected Components

Topological Sorting and finding Strongly Connected Components are classical problems on Directed Graphs. Here we will see how we can do Topological Sorting by using DFS and Find Strongly Connected Components using Kosaraju's Algorithm.
Topological Sorting Algorithm:
1) Start with any node and perform a DFS on the graph marking visited nodes.
2) If a node has no unvisited neighbours, add it to the front of a linked list.
3) Repeat till all nodes are visited.
Instead of using a linked list we just push_back normally into a C++ vector. The final vector will give reverse of the topologically sorted order.
Strongly Connected Components Algorithm:
1) Do Topological Sort.
2) Find transpose of the graph: It is defined as - if (u,v) is an edge in original graph, (v,u) is an edge in the transpose
3) Do a DFS on the transpose of the graph in topologically sorted order.
4) Each vertex of the so formed depth-first forest is a separate strongly connected component. Mark them, count the number of them etc.
vector<int> a[1005],atr[1005],topo;
bool seen[1005];
int comp[1005],indeg[1005];
int n,c;

void dfs(int node) // Topological Sorting
{
 seen[node]=true;
 REP(i,0,a[node].size())
 {
  if(seen[a[node][i]]==false)
   dfs(a[node][i]);
 }
 topo.push_back(node);
}

void dfst(int node)
{
 seen[node]=true;
 comp[node]=c;
 REP(i,0,atr[node].size())
 {
  if(seen[atr[node][i]]==false)
   dfst(atr[node][i]);
 }
}

int SCC()
{
 int result=0;
 memset(seen, false, sizeof seen);
 REP(i,1,n+1)
 {
  if(seen[i]==false)
   dfs(i);
 }
 memset(seen,false,sizeof seen);
 memset(comp,0,sizeof comp);
 c=0;
 for(int i=topo.size()-1;i>=0;i--)
 {
  if(seen[topo[i]]==false)
   {dfst(topo[i]);c++;}
 }
 return c;
}
Practice Problem:
CAPCITY

Kruskal's Algorithm for Minimum Spanning Tree

Kruskal's Algorithm is a Greedy algorithm which calculates the Minimum Spanning Tree of an undirected graph. It works as follows:
1) Sort the edges according to their weight.
2) Choose the edge with minimum weight
3) Take the next minimum edge - if it does not form a cycle with the existing edges in the MST, add it to the MST. Else, go to the next edge and repeat this step.
To check whether the next edge does not form a cycle with the existing edges, we use a Data Structure called Union-Find or Disjoint Set Data Structure. This can be implemented using arrays. To keep complexity minimum, we use Union-By-Rank and Path Compression.
Hence overall complexity of the algorithm is O(ElogE) for sorting + O(E) for the Disjoint-Set Data Structure operations = Overall O(ElogE).
#define MAXN 10000 // number of edges

struct node
{
    int x;
    int y;
    int w;
}e[MAXN];

int id[MAXN],sz[MAXN];

int root(int i)
{
    while(i!=id[i])
    {
        id[i]=id[id[i]];
        i=id[i];
    }
    return i;
}

void qunion(int p, int q)
{
    int i = root(p), j=root(q);
    if(sz[i] < sz[j]) {id[i]=j; sz[j]+=sz[i];}
    else                {id[j]=id[i]; sz[i]+=sz[j];}
}

bool fun(const node &a, const node &b)
{
    return a.w < b.w;
}

int main()
{
    int t,n,u,v,w,ans,k,adj;
    n=GI; k=0; ans=0;
    // Take input of edges, their weights and set id[i]=i, sz[i]=1 for each vertex
    REP(i,0,n)
    {
      e[k].x=GI; e[k].y=GI; e[k].w=GI;
      id[e[k].x]=e[k].x; id[e[k].y]=e[k].y; sz[e[k].x]=1; sz[e[k].y]=1;
      k++;
    }
    sort(e,e+k,fun);
    REP(i,0,k)
    {
      if(root(e[i].x)!=root(e[i].y))
      {
        qunion(e[i].x,e[i].y);
        ans+=e[i].w;
      }
    }
 printf("%d\n",ans);
 return 0;
}
Practice Problem:
BLINNET

Sieve Of Eratosthenes – Primality testing for numbers in a range

If u want to generate a list of all the primes in the range "1 to n" then a very simple to code algorithm which u can use is Sieve Of Eratosthenes.

The sieve algorithm explained in simple words is:
1) Mark all numbers in the range as prime.
2) Mark 1 to be trivially not prime
3) Mark even numbers (except two) to be trivially not prime.
4) Start from i = 3 (next number which is marked true) and mark all its multiples from i*i to n as not prime.
5) Continue no. 4 for all i till sqrt(n).

bool flag[n+1];
memset(flag, true, sizeof flag);
flag[1] = false;
for(int i=4; i <= n; i+=2)
 flag[i] = false;
for(int i=3; i <= sqrt(n); i+=2)
{
  if(flag[i])
    for(int j=i*i; j<=n; j += i)
      flag[j] = false;
}
Complexity of the algorithm is O(n log log n) in terms of arithmetic operations.

Now, you can use this base table to solve a wide variety of problems involving prime numbers.

Practice Problem:
PRIME1

ex-Opti: An Expense Management System.

eX-Opti is a multi-platform expense management system built on the Cloud and hosted on Google App Engine.It can be accessed either through a PC or a mobile web browser (www.ex-opti.appspot.com) or through telephony (Call +91-4466949325). It was built as a part of Desert Hack, a 2 day hackathon. It was also my first Cloud based App venture.
Some of its features are:
  • Add expense entries feature-wise.
  • View details and analytics of past spendings, over a custom range of days.
  • View graphs of category-wise spending.
  • A mobile call can be used to update the spendings (for the large user base with no mobile internet in India) - using DTMF.
Technical details of the app:
  • Built using Google App Engine, Python, JavaScript and HTML
  • Site is optimized for mobile - using jQuery Mobile.
  • Uses Kookoo API for telephony support and Google Charts API for generating charts of Analytics.
U can watch the App Demo which we made here:

The project is now hosted open source on Github. Feel free to fork/clone it and develop it further.

Competition Programming Template

In Competition Programming, where speed of solving problems matter, it is good to create a template of useful libraries, commonly used statements like for loops simplified using #define and some typedefs for things like long long, pair<int,int> etc. These make ur coding speed faster as u often have lesser code to type and the resulting code becomes more readable as well. However overuse of such templates might spoil your coding style and make your code unreadable by anyone else. So be wary of their use.
Here is my programming template in C++:
# include <iostream>
# include <fstream>
# include <sstream>
# include <algorithm>
# include <cstdio>
# include <cmath>
# include <numeric>
# include <cstdlib>
# include <cstring>
# include <vector>
# include <list>
# include <set>
# include <map>
# include <stack>
# include <queue>
# include <cctype>
# include <climits>
# include <complex>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,PII> TRI;
typedef vector<string> VS;

#define GI ({int t;scanf("%d",&t);t;})
#define REP(i,a,b) for(int i=a;i<b;i++)
#define FOR(i,n) REP(i,0,n)
#define ALL(v) (v).begin(),(v).end()
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define bitcount(x) __builtin_popcount(x)
#define pb push_back
#define mp make_pair
#define mt(a,b,c) mp(a,mp(b,c))
#define EPS (double)(1e-9)
#define INF 1000000000
#define MOD 1000000007
#define PI (double)(3.141592653589793)

inline int ni()
{
 register int r=0,c;
 for(c=getchar_unlocked();c<=32;c=getchar_unlocked());
 if(c=='-')
  return -ni();
 for(;c>32;r=(r<<1)+(r<<3)+c-'0',c=getchar_unlocked());
 return r;
}

int main()
{
 int t;
 t = ni();
 while(t--) {
  
 }
 return 0;
}
If you are use windows while coding, u might also find it useful to use:
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
to test your code.

Generating all subsets of a set

Sometimes, u need to enumerate all possible subsets of a size n as a sub-problem of some bigger problem. This can be done using bitmasks (ie) using bits of an integer to represent whether the element is there in the current subset(bit is 'set' or 1) or it is not in the current subset(bit is 'not set' or 0). C++ code with explanation follows:
int n=10; // size of set
int n2=1<<n; // set of size n has 2^n subsets
for(int i=1;i<n2;i++)
{
 mask = i;
 pos=n-1;
 while(mask>0)
 {
  if((mask&1)==1)
  {
  // Element at pos belongs to the current subset.
  }
  mask>>=1;
  pos--;
 }
}

ICPC Amrita Online Contest 2012 -- Editorials

This is my first attempt at writing an editorial, so please correct me if there are any errors and suggest improvements.
General Comments about the Contest:
There were 5 problems in all. I felt that the problems were arranged in the increasing order of difficulty (as can also be seen by the final rank list). The conduction of the contest was not so good as the server crashed multiple times throughout the competition.
U can download the complete Problem Set here: icpcquestions.docx
For solutions to the problems, i have used my C++ Competition Programming Template which u can find here. I have not included them in the solutions posted here for the sake of simplicity.
The Problems:
A: Pair Socks
Given a string containing a series of characters 'R', 'G', 'B' and 'W' representing red, green, blue and white socks, find if each of these can be grouped in pairs of same colour.
Solution:
A very trivial problem. Count the number of occurrences of each character. If all of the counts are divisible by 2, then it is possible - print 'YES'. Otherwise print 'NO'.
int main()
{
 int t,r=0,g=0,b=0,w=0;
 string s;
 t=GI;
 while(t--)
 {
  r=0;g=0;b=0;w=0;
  cin>>s;
  REP(i,0,s.size())
  {
   if(s[i]=='R') r+=1;
   if(s[i]=='G') g+=1;
   if(s[i]=='B') b+=1;
   if(s[i]=='W') w+=1;
  }
  if(r%2==0 && g%2==0 && b%2==0 && w%2==0)
   printf("YES\n");
  else
   printf("NO\n");
 }
 return 0;
}
B: Sticks
You have N sticks - the length of the ith stick being L[i]. You also have M 3-dimensional boxes - the length, breadth and height of the jth box being A[j], B[j] and C[j]. What is the maximum number of sticks which can fit in the boxes? A stick can be fit in a box if it can be placed within it without bending or cutting it. A box can hold any number of fitting sicks (assume that the sticks do not intersect each other).
Solution:
Again a trivial problem, but had a small trick in the implementation. Since a box can hold any number of fitting sticks, we can just take the largest box and check whether we can put each of the sticks into it oriented across the body diagonal (ie) from (0,0,0) to (A[i],B[i],C[i]). The trick in this problem is that A[i]*A[i] + B[i]*B[i] + C[i]*C[i] would overflow if u were using integer values. So if u declare them as long/long long u will be fine.
int main()
{
 int t, n, m, cnt;
 LL l[100005],x,y,z,val;
 t=GI;
 while(t--)
 {
  cnt=0;val=0;
  n=GI; m=GI;
  REP(i,0,n)
  {
   l[i]=GI;
  }
  REP(i,0,m)
  {
   x=GI; y=GI; z=GI;
   val = max(val,x*x+y*y+z*z);
  }
  REP(i,0,n)
  {
   if(l[i]*l[i]<=val)
    cnt++;
  }
  printf("%d\n",cnt);
 }
 return 0;
}
C: Sum Range

You are given N numbers a[1..N] and 2 other integers L and H. Count the number of tuples (i,j,k) satisfying i < j < k and L <= a[i] + a[j] + a[k] <= H.
Solution:
Probably the trickiest problem of them all (not toughest), both to implement as well as to understand why the complexity of the solution is O(n^2) inspite of having three nested for loops.
Firstly, we can see that order of the original array does not matter (since even if the order is changed, the three elements can be rearranged to match their order in the original array so that the i<j<k condition is satisfied). So we sort the original array. Now, we can reduce the problem statement to iterating across all possible i and k (ie) from left and right ends of the array and finding the number of possible j indices for each of them. This might sound like an O(n^3) solution, but we avoid that by maintaining the lowest  value j can take and the highest value j can take - this reduces the complexity to O(n^2).
A simpler solution to this problem in O(N^2logN) is also possible using binary search, which also passed the time limit.
int main()
{
 int t, n, l, h, a[1005],j,p;
 LL cnt;
 t=GI;
 while(t--)
 {
  cnt=0;
  n=GI; l=GI; h=GI;
  REP(i,0,n)
   a[i]=GI;
  sort(a,a+n);
  REP(i,0,n-2)
  {
   j=i+1;
   p=i+1;
   for(int k=n-1;k>i+1;k--)
   {
    for(;j<k;j++)
    {
     if(a[i]+a[j]+a[k]>=l)
      break;
    }
    for(;p<k;p++)
    {
     if(a[i]+a[p]+a[k]>h)
      break;
    }
    if(p>i+1)
     p--;
    if(a[i]+a[j]+a[k]>=l && a[i]+a[p]+a[k]<=h && j<=p && j>i)
     cnt+=(p-j+1);
   }
  }
  printf("%lld\n",cnt);
 }
 return 0;
}
D: Team Division

Given a list of teams and their perceived rival team list, find the number of ways that u can divide them into two groups such that no team is in the same group as its rival team.
Solution:
There was a small confusion in the statement "The rivalry relation is not symmetric". It means that in the given input data, a is a rival of b doesn't mean that b will be a rival of a. However, when we assign teams we need to make sure that if either a is a perceived rival of b or b is a perceived rival of a, both shouldn't be in the same site. This can be handled by simply adding a to b's list of rivals and b to a's list of rivals if either one perceives the other as a rival.
Then, we can perform a DFS on all the nodes to separate them into bipartite components (ie) components in which one group should be in a different site than the other. The answer would then be 2^(number of components). When performing the DFS, if we see that such a bipartite division is not possible, then no division is possible. So we can output '0' in that case.
int a[20005],b[20005],cnt,num,val;
pair<int,int> top;
set<int> v[20005];
bool seen[20005];

LL mod_exp(int cnt)
{
 if(cnt==1)
  return 2;
 if(cnt%2==0)
 {
  LL temp=mod_exp(cnt/2);
  return (temp*temp)%MOD;
 }
 else
 {
  LL temp=mod_exp(cnt-1);
  return (2*temp)%MOD;
 }
}

int main()
{
 int t, n;
 t=GI;
 while(t--)
 {
  memset(a,-1,sizeof a);
  memset(b,-1,sizeof b);
  memset(seen,false,sizeof seen);
  cnt=0;
  n=GI;
  REP(i,0,n)
   v[i].clear();
  REP(i,0,n)
  {
   num=GI;
   REP(j,0,num)
   {
    val=GI;
    if(v[i].find(val)==v[i].end())
     v[i].insert(val);
    if(v[val].find(i)==v[val].end())
     v[val].insert(i);
   }
  }

  REP(i,0,n)
  {
   if(seen[i]) continue;
   seen[i]=true;
   cnt++;
   a[i]=cnt;
   stack<pair<int,int> >s;
   TR(it,v[i])
   {
    s.push(mp(*it,1));
   }
   while(!s.empty())
   {
    top=s.top();s.pop();
    if(seen[top.first]) continue;
    seen[top.first]=true;
    TR(it,v[top.first])
    {
     if(seen[*it]) continue;

     if(top.second==0)
     {
      if(a[*it]!=-1)
      {
       printf("0\n");
       goto next;
      }
      s.push(mp(*it,1));
      b[*it]=cnt;
     }
     if(top.second==1)
     {
      if(b[*it]!=-1)
      {
       printf("0\n");
       goto next;
      }
      s.push(mp(*it,0));
      a[*it]=cnt;
     }
    }
   }
  }
  printf("%lld\n",mod_exp(cnt)); // second time
  next:;
 }
 return 0;
}
E: Sequence

Given a sequence S of '0' and '1' of length N, a subsequence of S is obtained by omitting some elements of S without changing the order of the remaining elements of S.
Given a subarray of a sequence S starting from some position 'a' and ending at some position 'b' (1 <= a <= b <= N), both inclusive, denoted by S(a,b), you have report the length of longest non-decreasing subsequence of S(a,b). By non-decreasing, we mean that a '0' never appears after a '1' in the subsequence.
1<=Number of elements in the array<=10000, 1<=Number of queries<=100000.
Solution:
This problem required the use of a data structure called a segment tree. A segment tree is a data structure which allows u to do range queries like maximum, sum, frequency etc. in an interval in O(logN) time with O(N) pre-processing. Read the description of how to construct this here - http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor
Now, the solution of the problem.
Maintain three things in the segment tree - a, z and o.
a - length of longest subsequence in an interval
z - number of zeros in an interval
o - number of ones in an interval
We can combine the segments as follows during initialization:
a[n] = max(a[2*n] + o[2*n+1], z[2*n] + a[2*n+1])
z[n] = z[2*n] + z[2*n+1]
o[n] = o[2*n] + o[2*n+1]
Similar query function.
#define MAXN 1000000
struct rsq
{
 int a;
 int o;
 int z;
}tree[MAXN];
string s;

void init(int n, int b, int e)
{
 if(b==e)
 {
  if(s[b]=='0') tree[n].a=tree[n].z=1,tree[n].o=0;
  else  tree[n].a=tree[n].o=1,tree[n].z=0;
 }
 else
 {
  init(2*n,b,(b+e)/2);
  init(2*n+1,(b+e)/2+1,e);
  tree[n].o = tree[2*n].o + tree[2*n+1].o;
  tree[n].z = tree[2*n].z + tree[2*n+1].z;
  tree[n].a = max(tree[2*n].a+tree[2*n+1].o,tree[2*n].z+tree[2*n+1].a);
 }
}

rsq query(int n, int b, int e, int i, int j)
{
 if(i<=b && j>=e)
  return tree[n];
 int mid=(b+e)/2;
 if(j<=mid)
  return query(2*n,b,mid,i,j);
 if(i>mid)
  return query(2*n+1,mid+1,e,i,j);

 rsq x,y,ans;
 x = query(2*n,b,mid,i,j);
 y = query(2*n+1,mid+1,e,i,j);
 ans.o = x.o + y.o;
 ans.z = x.z + y.z;
 ans.a = max( x.a+y.o, x.z+y.a );

 return ans;
}

int main()
{
 int n,q,t,x,y;
 t=GI;
 while(t--)
 {
  n=GI;
  REP(i,0,n+1) tree[i].a=tree[i].o=tree[i].z=0;
  cin>>s;
  s=" "+s;
  init(1,1,n);
  q=GI;
  REP(i,0,q)
  {
   x=GI; y=GI;
   printf("%d\n",query(1,1,n,x,y).a);
  }
 }
 return 0;
}
Feel free to leave any comments, suggestions, alternative solutions in the comments below.