0% found this document useful (0 votes)
6 views13 pages

Competitive Programming Techniques Guide

The document provides an overview of competitive programming and various algorithmic techniques including bit manipulation, divide and conquer, two pointers, sliding window, hashing, and dynamic programming. It includes explanations, visualizations, and code examples for each technique, highlighting their applications and problem-solving strategies. Key topics also cover specific problems like the Knapsack problem, Longest Common Subsequence, and Longest Increasing Subsequence.

Uploaded by

pramodchavan092
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views13 pages

Competitive Programming Techniques Guide

The document provides an overview of competitive programming and various algorithmic techniques including bit manipulation, divide and conquer, two pointers, sliding window, hashing, and dynamic programming. It includes explanations, visualizations, and code examples for each technique, highlighting their applications and problem-solving strategies. Key topics also cover specific problems like the Knapsack problem, Longest Common Subsequence, and Longest Increasing Subsequence.

Uploaded by

pramodchavan092
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

UNIT – V: Competitive Programming and Dynamic Programming

1. Introduction to Competitive Programming

Competitive Programming (CP) is a problem-solving approach where programmers solve


algorithmic problems efficiently under time and memory constraints. It focuses on:

 Logical thinking

 Optimized algorithms

 Efficient data structures

Key Characteristics

 Multiple test cases

 Strict time limits (usually 1–2 seconds)

 Emphasis on time and space optimization

2. Bit Manipulation Techniques

Bit manipulation uses binary representation of numbers to perform operations efficiently.

Common Bitwise Operators

Operator Symbol Description

AND & Sets bit if both bits are 1

OR | Sets bit if at least one bit is 1

XOR ^ Sets bit if bits are different

NOT ~ Inverts bits

Left Shift << Shifts bits to left

Right Shift >> Shifts bits to right

Visualization (Binary Representation)

Number: 5

Binary: 0101

5 << 1 = 1010 (10)


5 >> 1 = 0010 (2)

Example: Check if a number is even or odd

#include <iostream>

using namespace std;

int main() {

int n = 7;

if (n & 1)

cout << "Odd";

else

cout << "Even";

return 0;

Application of Bitwise Operator

 Bitwise operations are prominent in embedded systems, control systems, etc where
memory(data transmission/data points) is still an issue.

 They are also useful in networking where it is important to reduce the amount of
data, so booleans are packed together. Packing them together and taking them apart
use bitwise operations and shift instructions.

 Bitwise operations are also heavily used in the compression and encryption of data.

 Useful in graphics programming, older GUIs are heavily dependent on bitwise


operations like XOR(^) for selection highlighting and other overlays.

3. Divide and Conquer Technique

Divide and Conquer breaks a problem into smaller subproblems, solves them independently,
and combines their results.

Steps

 Divide: Dividing the problem into two or more than two sub-problems that are
similar to the original problem but smaller in size.
 Conquer: Solve the sub-problems recursively.

 Combine: Combine these solutions to subproblems to create a solution to the


original problem.

Visualization

Array: [8,7,4,2,9,1,5,6]
Example: Merge Sort

#include <iostream>

using namespace std;

void merge(int arr[], int l, int m, int r) {

int n1 = m - l + 1;

int n2 = r - m;

int L[n1], R[n2];

for(int i=0;i<n1;i++) L[i] = arr[l+i];

for(int j=0;j<n2;j++) R[j] = arr[m+1+j];

int i=0, j=0, k=l;

while(i<n1 && j<n2) {

if(L[i] <= R[j]) arr[k++] = L[i++];

else arr[k++] = R[j++];

while(i<n1) arr[k++] = L[i++];

while(j<n2) arr[k++] = R[j++];

void mergeSort(int arr[], int l, int r) {

if(l < r) {

int m = l + (r-l)/2;

mergeSort(arr, l, m);

mergeSort(arr, m+1, r);

merge(arr, l, m, r);

}
}

4. Two Pointer Technique

The Two-Pointers Technique is a simple yet powerful strategy where you use two indices
(pointers) that traverse a data structure—such as an array, list, or string—either toward each
other or in the same direction to solve problems more efficiently

Two pointers is really an easy and effective technique that is typically used for Two Sum in
Sorted Arrays, Closest Two Sum, Three Sum, Four Sum, Trapping Rain Water and many other
popular questions.

When to Use Two Pointers:

 Sorted Input : If the array or list is already sorted (or can be sorted), two pointers can
efficiently find pairs or ranges. Example: Find two numbers in a sorted array that add
up to a target.

 Pairs or Subarrays : When the problem asks about two elements, subarrays, or
ranges instead of working with single elements. Example: Longest substring without
repeating characters, maximum consecutive ones, checking if a string is palindrome.

 Sliding Window Problems : When you need to maintain a window of elements that
grows/shrinks based on conditions. Example: Find smallest subarray with sum ≥ K,
move all zeros to end while maintaining order.

 Linked Lists (Slow–Fast pointers) : Detecting cycles, finding the middle node, or
checking palindrome property. Example: Floyd’s Cycle Detection Algorithm (Tortoise
and Hare).

Visualization
Example: Pair with given sum

#include <iostream>

#include <vector>

using namespace std;

bool twoSum(vector<int> &arr, int target){

int start = 0, end = [Link]() - 1;

while (start < end){

int sum = arr[start] + arr[end];

if (sum == target)

return true;

// Move toward a higher sum

else if (sum < target)

start++;
// Move toward a lower sum

else

end--;

// If no pair found

return false;

int main(){

vector<int> arr = {2,3,3,4,6,8,8,10};

int target = 11;

if (twoSum(arr, target))

cout << "true";

else

cout << "false";

return 0;

5. Sliding Window Technique

Sliding Window Technique is a method used to solve problems that involve subarray or
substring or window.

 Instead of repeatedly iterating over the same elements, the sliding window maintains
a range (or “window”) that moves step-by-step through the data, updating results
incrementally.

 The main idea is to use the results of previous window to do computations for the
next window.
 Commonly used for problems like finding subarrays with a specific sum, finding the
longest substring with unique characters, or solving problems that require a fixed-
size window to process elements efficiently.

Visualization

Example: Maximum sum subarray of size k

#include <iostream>

using namespace std;

int main() {

int arr[] = {2,1,5,1,3,2};

int k = 3, n = 6;

int windowSum = 0, maxSum = 0;

for(int i=0;i<k;i++) windowSum += arr[i];

maxSum = windowSum;

for(int i=k;i<n;i++) {
windowSum += arr[i] - arr[i-k];

maxSum = max(maxSum, windowSum);

cout << maxSum;

return 0;

6. Hashing Techniques

Hashing maps data to an index using a hash function for fast access.

Types of Hashing

 Chaining

 Open Addressing (Linear Probing)

Visualization (Chaining)

Index 0 → 10 → 20

Index 1 → 15

Example: Frequency Count using Hash Map

#include <iostream>

#include <unordered_map>

using namespace std;

int main() {

int arr[] = {1,2,2,3,1};

unordered_map<int,int> freq;

for(int x : arr) freq[x]++;

for(auto p : freq)

cout << [Link] << " -> " << [Link] << endl;

return 0;
}

7. Dynamic Programming (DP)

Dynamic Programming solves problems by breaking them into overlapping subproblems


and storing results.

Two Approaches

Method Description

Memoization Top-down (Recursion + Storage)

Tabulation Bottom-up (Iterative)

8. Fibonacci using DP

Visualization

F(5)

→ F(4) + F(3)

→ Stored results reused

Tabulation Code

#include <iostream>

using namespace std;

int main() {

int n = 5;

int dp[n+1];

dp[0] = 0;

dp[1] = 1;

for(int i=2;i<=n;i++)

dp[i] = dp[i-1] + dp[i-2];

cout << dp[n];

return 0;
}

9. Knapsack Problem (0/1 Knapsack)

Problem Statement

Given weights and values, select items to maximize value without exceeding capacity.

Visualization

Items: (w,v)

(1,1) (3,4) (4,5)

Capacity = 4

Code

#include <iostream>

using namespace std;

int main() {

int wt[] = {1,3,4};

int val[] = {1,4,5};

int W = 4, n = 3;

int dp[n+1][W+1];

for(int i=0;i<=n;i++) {

for(int w=0;w<=W;w++) {

if(i==0 || w==0) dp[i][w] = 0;

else if(wt[i-1] <= w)

dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]);

else dp[i][w] = dp[i-1][w];

cout << dp[n][W];


return 0;

10. Longest Common Subsequence (LCS)

Visualization

X = ABCD

Y = AEB D

LCS = ABD

Code

#include <iostream>

#include <cstring>

using namespace std;

int main() {

char X[] = "ABCD";

char Y[] = "AEB D";

int m = strlen(X);

int n = strlen(Y);

int dp[m+1][n+1];

for(int i=0;i<=m;i++) {

for(int j=0;j<=n;j++) {

if(i==0 || j==0) dp[i][j] = 0;

else if(X[i-1] == Y[j-1]) dp[i][j] = dp[i-1][j-1] + 1;

else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);

cout << dp[m][n];


return 0;

11. Longest Increasing Subsequence (LIS)

Visualization

Array: [10,9,2,5,3,7]

LIS = [2,5,7]

Code

#include <iostream>

using namespace std;

int main() {

int arr[] = {10,9,2,5,3,7};

int n = 6;

int dp[n];

for(int i=0;i<n;i++) dp[i] = 1;

for(int i=1;i<n;i++)

for(int j=0;j<i;j++)

if(arr[i] > arr[j])

dp[i] = max(dp[i], dp[j] + 1);

int ans = 0;

for(int i=0;i<n;i++) ans = max(ans, dp[i]);

cout << ans;

return 0;

You might also like