Problem:
Score : 200 points

Problem Statement

We have A cards, each of which has an integer 1 written on it. Similarly, we also have B cards with 0s and C cards with -1s.

We will pick up K among these cards. What is the maximum possible sum of the numbers written on the cards chosen?

Constraints

All values in input are integers.

0 \leq A, B, C

1 \leq K \leq A + B + C \leq 2 \times 10^9

Input

Input is given from Standard Input in the following format:

A B C K

Output

Print the maximum possible sum of the numbers written on the cards chosen.

Sample Input 1

2 1 1 3

Sample Output 1

2

Consider picking up two cards with 1s and one card with a 0.
In this case, the sum of the numbers written on the cards is 2, which is the maximum possible value.

Sample Input 2

1 2 3 4

Sample Output 2

0

Sample Input 3

2000000000 0 0 2000000000

Sample Output 3

2000000000

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using static System.Console;

namespace Core3_1
{
	public static class Program
	{
		public static void Main(string[] args)
		{
			ReadLine()
				.SplitToIntList()
				.ToVariable(out var data);
			if (data[3] <= data[0])
			{
				WriteLine(data[3]);
				return;
			}
			data[3] -= data[0];
			if (data[3] <= data[1])
			{
				WriteLine(data[0]);
				return;
			}
			data[3] -= data[1];
			WriteLine(data[0] - data[3]);
		}

		#region Utilities

		public interface IBuffer<out T> : IEnumerable<T>, IDisposable
		{ }

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			int count)
		{
			return Buffer(source, count, count);
		}

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			int count,
			int skip)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (count < 1)
				throw new ArgumentOutOfRangeException(nameof(count));
			if (skip < 1)
				throw new ArgumentOutOfRangeException(nameof(skip));

			var queue = new Queue<List<T>>();
			int step = skip;
			foreach (var item in source)
			{
				if (step == skip)
				{
					step = 0;
					queue.Enqueue(new List<T>(count));
				}
				foreach (var list in queue)
					list.Add(item);
				while (queue.Count > 0 && queue.Peek().Count == count)
					yield return queue.Dequeue();
				step++;
			}
			while (queue.Count > 0) yield return queue.Dequeue();
		}

		public static IEnumerable<IList<T>> Buffer<T>(
			this IEnumerable<T> source,
			Func<T, bool> seperator,
			bool includeSeperator = false)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (seperator == null)
				throw new ArgumentNullException(nameof(seperator));

			var list = new List<T>();
			foreach (var item in source)
			{
				if (seperator(item))
				{
					if (includeSeperator) list.Add(item);
					yield return list;
					list = new List<T>();
				}
				else
				{
					list.Add(item);
				}
			}
			yield return list;
		}

		public static TResult Chain<TSource, TResult>(
			this TSource source,
			Func<TSource, TResult> selector)
		{
			return selector(source);
		}

		public static T Chain<T>(
			this T source,
			Action<T> action)
		{
			action(source);
			return source;
		}

		public static IEnumerable<IEnumerable<T>> Combination<T>(
			this IEnumerable<T> source,
			int count)
		{
			var stack = new Stack<List<T>[]>();
			stack.Push(new[]
			{
				new List<T>(),
				source.ToList()
			});
			while (stack.Count > 0)
			{
				var item = stack.Pop();
				if (item[0].Count() == count)
				{
					yield return item[0];
				}
				else
				{
					var list = item[1];
					list
						.Select((a, i) => new[]
						{
							item[0].Concat(new[]{ a }).ToList(),
							list.Skip(i + 1).ToList(),
						})
						.TakeWhile(a => a[0].Count + a[1].Count >= count)
						.ForEach(a => stack.Push(a));
				}
			}
		}

		public static IEnumerable<T> Concat<T>(this IEnumerable<IEnumerable<T>> source)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));

			return source.SelectMany(a => a);
		}

		public static IEnumerable<T> Do<T>(
			this IEnumerable<T> source,
			Action<T> action)
		{
			foreach (var a in source)
			{
				action(a);
				yield return a;
			}
		}

		public static void ForEach<T>(
			this IEnumerable<T> source,
			Action<T> unlessEmpty,
			Action ifEmpty = null)
		{
			if (unlessEmpty == null)
				throw new ArgumentNullException(nameof(unlessEmpty));

			using var e = source.GetEnumerator();
			if (e.MoveNext())
			{
				do unlessEmpty(e.Current);
				while (e.MoveNext());
			}
			else
			{
				ifEmpty?.Invoke();
			}
		}

		public static void ForEach<T>(
			this IEnumerable<T> source,
			Action<T, int> unlessEmpty,
			Action ifEmpty = null)
		{
			if (unlessEmpty == null)
				throw new ArgumentNullException(nameof(unlessEmpty));

			using var e = source.GetEnumerator();
			if (e.MoveNext())
			{
				int i = 0;
				do
				{
					unlessEmpty(e.Current, i);
					i++;
				} while (e.MoveNext());
			}
			else
			{
				ifEmpty?.Invoke();
			}
		}

		public static string JoinWithSpace<T>(this IEnumerable<T> source)
		{
			return string.Join(" ", source);
		}

		public static IEnumerable<IEnumerable<T>> Permutation<T>(
			this IEnumerable<T> source,
			int count)
		{
			var stack = new Stack<IEnumerable<T>[]>();
			stack.Push(new[]
			{
				Enumerable.Empty<T>(),
				source.ToList()
			});
			while (stack.Count > 0)
			{
				var item = stack.Pop();
				if (item[0].Count() == count)
				{
					yield return item[0];
				}
				else
				{
					var list = item[1];
					list
						.Select((a, i) => new[]
						{
							item[0].Concat(new[]{ a }),
							list.Where((b, j) => j != i),
						})
						.ForEach(a => stack.Push(a));
				}
			}
		}

		public static IEnumerable<string> ReadAllLines()
		{
			return Repeat(ReadLine).TakeWhile(a => a != null);
		}

		public static IEnumerable<T> Recurse<T>(
			this T source,
			Func<T, T> selector)
		{
			var p = source;
			while (true)
			{
				yield return p;
				p = selector(p);
			}
		}

		public static IEnumerable<T> Repeat<T>(this T source)
		{
			return Repeat(() => source);
		}

		public static IEnumerable<T> Repeat<T>(Func<T> selector)
		{
			while (true) yield return selector();
		}

		public static IEnumerable<T> Return<T>(params T[] source)
		{
			return source;
		}

		public static IEnumerable<T> Scan<T>(
			this IEnumerable<T> source,
			Func<T, T, T> selector)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (selector == null)
				throw new ArgumentNullException(nameof(selector));

			using var enumerator = source.GetEnumerator();
			if (enumerator.MoveNext())
			{
				var last = enumerator.Current;
				while (enumerator.MoveNext())
				{
					last = selector(last, enumerator.Current);
					yield return last;
				}
			}
		}

		public static IEnumerable<T> Scan<T>(
			this IEnumerable<T> source,
			T seed,
			Func<T, T, T> selector)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (selector == null)
				throw new ArgumentNullException(nameof(selector));

			var last = seed;
			foreach (var item in source)
			{
				last = selector(last, item);
				yield return last;
			}
		}

		public static IBuffer<T> Share<T>(this IEnumerable<T> source)
		{
			return new SharedBuffer<T>(source);
		}

		public static List<double> SplitToDoubleList(this string source)
		{
			return source.Split().Select(a => double.Parse(a)).ToList();
		}

		public static List<int> SplitToIntList(this string source)
		{
			return source.Split().Select(a => int.Parse(a)).ToList();
		}

		public static List<long> SplitToLongList(this string source)
		{
			return source.Split().Select(a => long.Parse(a)).ToList();
		}

		public static List<ulong> SplitToUlongList(this string source)
		{
			return source.Split().Select(a => ulong.Parse(a)).ToList();
		}

		public static T ToVariable<T>(this T source, out T variable)
		{
			variable = source;
			return source;
		}

		public static void WriteAllLines<T>(this IEnumerable<T> source)
		{
			foreach (var item in source) WriteLine(item);
		}

		public static T WriteLine<T>(this T source)
		{
			Console.WriteLine(source);
			return source;
		}

		class SharedBuffer<T> : IBuffer<T>
		{
			private IEnumerator<T> enumerator;

			public SharedBuffer(IEnumerable<T> source)
			{
				enumerator = source.GetEnumerator();
			}

			public void Dispose()
			{
				if (enumerator == null) return;
				enumerator.Dispose();
				enumerator = null;
			}

			public IEnumerator<T> GetEnumerator()
			{
				if (enumerator != null)
				{
					while (enumerator.MoveNext())
					{
						yield return enumerator.Current;
					}
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		#endregion

		#region Location

		struct Location
		{
			public Location(int x, int y)
			{
				X = x;
				Y = y;
			}

			public int X { get; private set; }
			public int Y { get; private set; }

			public static Location operator -(Location left, Location right)
			{
				return new Location(left.X - right.X, left.Y - right.Y);
			}

			public static bool operator !=(Location left, Location right)
			{
				return !(left == right);
			}

			public static Location operator +(Location left, Location right)
			{
				return new Location(left.X + right.X, left.Y + right.Y);
			}

			public static bool operator ==(Location left, Location right)
			{
				return EqualityComparer<Location>.Default.Equals(left, right);
			}

			public override bool Equals(object obj)
			{
				if (!(obj is Location)) return false;
				var other = (Location)obj;
				return other != null &&
					   X == other.X &&
					   Y == other.Y;
			}

			public override int GetHashCode()
			{
				return X << 16 | Y | X >> 16;
			}

			public override string ToString()
			{
				return $"({X},{Y})";
			}
		}

		#endregion

		#region D2

		class D2<T> : IEnumerable<Location>
		{
			public D2(int width, int height, IEnumerable<T> items = null)
			{
				Width = width;
				Height = height;
				var size = Width * Height;
				Items = items?.ToArray() ?? new T[size];
				if (Items.Length != size) throw new Exception();
			}

			public int Height { get; private set; }
			public T[] Items { get; private set; }
			public int Width { get; private set; }

			public T this[int index]
			{
				get { return Items[index]; }
				set { Items[index] = value; }
			}

			public T this[int x, int y]
			{
				get { return Items[y * Width + x]; }
				set { Items[y * Width + x] = value; }
			}

			public T this[Location location]
			{
				get { return this[location.X, location.Y]; }
				set { this[location.X, location.Y] = value; }
			}

			public D2<T> Clone()
			{
				return new D2<T>(Width, Height, Items);
			}

			public bool Contains(Location location)
			{
				return 0 <= location.X
					&& 0 <= location.Y
					&& location.X < Width
					&& location.Y < Height;
			}

			public IEnumerable<IEnumerable<Location>> EnumerateHorizontal()
			{
				return Enumerable
					.Range(0, Width)
					.Select(x => Enumerable
						.Range(0, Height)
						.Select(y => new Location(x, y)));
			}

			public IEnumerable<IEnumerable<Location>> EnumerateVertical()
			{
				return Enumerable
					.Range(0, Height)
					.Select(y => Enumerable
						.Range(0, Width)
						.Select(x => new Location(x, y)));
			}

			public IEnumerator<Location> GetEnumerator()
			{
				foreach (var item in EnumerateVertical().SelectMany(a => a))
				{
					yield return item;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		#endregion

		#region Matrix

		class Matrix : D2<double>
		{
			public Matrix(int width, int height, IEnumerable<double> items = null) :
				base(width, height, items)
			{
			}

			public static Matrix operator -(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Width || left.Height != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					left.Width,
					left.Height,
					left.Items.Zip(right.Items, (a, b) => a - b));
			}

			public static Matrix operator -(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a - right));
			}

			public static bool operator !=(Matrix left, Matrix right)
			{
				return !(left == right);
			}

			public static Matrix operator *(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					right.Width,
					left.Height,
					left
						.EnumerateVertical()
						.SelectMany(l => right
							.EnumerateHorizontal()
							.Select(r => l.Zip(r, (a, b) => left[a] * right[b]).Sum())));
			}

			public static Matrix operator *(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a * right));
			}

			public static Matrix operator /(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a / right));
			}

			public static Matrix operator +(Matrix left, Matrix right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				if (right == null) throw new ArgumentNullException(nameof(right));
				if (left.Width != right.Width || left.Height != right.Height)
					throw new ArgumentException(nameof(right));
				return new Matrix(
					left.Width,
					left.Height,
					left.Items.Zip(right.Items, (a, b) => a + b));
			}

			public static Matrix operator +(Matrix left, double right)
			{
				if (left == null) throw new ArgumentNullException(nameof(left));
				return new Matrix(left.Width, left.Height, left.Items.Select(a => a + right));
			}

			public static bool operator ==(Matrix left, Matrix right)
			{
				return EqualityComparer<Matrix>.Default.Equals(left, right);
			}

			public override bool Equals(object obj)
			{
				var other = obj as Matrix;
				return other != null
					&& Width == other.Width
					&& Height == other.Height
					&& Items.Zip(other.Items, (a, b) => a == b).All(a => a);
			}

			public override int GetHashCode()
			{
				int hashCode = 1931280238;
				hashCode = hashCode * -1521134295
					+ Width.GetHashCode()
					+ Height.GetHashCode()
					+ Items.Select(a => a.GetHashCode()).Aggregate((a, b) => a ^ b);
				return hashCode;
			}

			public virtual string ToString(string format)
			{
				return EnumerateVertical()
					.Select(a => string.Join(" ", a.Select(b => this[b].ToString(format))))
					.Chain(a => string.Join("\n", a));
			}

			public override string ToString()
			{
				return ToString("0.00000");
			}
		}

		class PitchMatrix : Matrix
		{
			public PitchMatrix(double radian) : base(3, 3, new[]
			{
				1, 0, 0,
				0, Math.Cos(radian), -Math.Sin(radian),
				0, Math.Sin(radian), Math.Cos(radian),
			})
			{ }

			public PitchMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class RollMatrix : Matrix
		{
			public RollMatrix(double radian) : base(3, 3, new[]
			{
				Math.Cos(radian), -Math.Sin(radian), 0,
				Math.Sin(radian), Math.Cos(radian), 0,
				0, 0, 1,
			})
			{ }

			public RollMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class RotationMatrix : Matrix
		{
			public RotationMatrix(double radian) : base(2, 2, new[]
			{
				Math.Cos(radian), -Math.Sin(radian),
				Math.Sin(radian), Math.Cos(radian),
			})
			{ }

			public RotationMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		class YawMatrix : Matrix
		{
			public YawMatrix(double radian) : base(3, 3, new[]
			{
				Math.Cos(radian), 0, -Math.Sin(radian),
				0, 1, 0,
				Math.Sin(radian), 0, Math.Cos(radian),
			})
			{ }

			public YawMatrix(int degree) : this(Math.PI * degree / 180)
			{ }
		}

		#endregion

		#region Prime

		class Prime
		{
			private static readonly bool[] buffer = new bool[4096];
			private static readonly List<int> list = new List<int>();
			private static int mark = 2;

			private Prime()
			{ }

			public static IEnumerable<int> Get()
			{
				return list.Concat(GetNew());
			}

			private static void FillBuffer()
			{
				Array.Clear(buffer, 0, buffer.Length);
				Enumerable
					.Range(0, list.Count)
					.Select(a => list[a])
					.ForEach(a =>
					{
						var o = mark % a;
						var n = o == 0 ? 0 : a - o;
						while (n < buffer.Length)
						{
							buffer[n] = true;
							n += a;
						}
					});
				Enumerable
					.Range(0, buffer.Length)
					.Where(a => !buffer[a])
					.Select(a => mark + a)
					.ForEach(a => (a * 2 - mark)
						.Recurse(b => b + a)
						.TakeWhile(b => b < buffer.Length)
						.ForEach(b => buffer[b] = true));
			}

			private static IEnumerable<int> GetNew()
			{
				while (true)
				{
					FillBuffer();
					int l = list.Count;
					Enumerable
						.Range(0, buffer.Length)
						.Where(a => !buffer[a])
						.ForEach(a => list.Add(mark + a));
					mark += buffer.Length;
					for (int i = l; i < list.Count; i++)
					{
						yield return list[i];
					}
				}
			}
		}

		#endregion
	}
}