using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Linq; using E = System.Linq.Enumerable; internal partial class Solver { public void Run() { var n = ni(); var xa = new int[n]; var ya = new int[n]; var xb = new int[n]; var yb = new int[n]; for (int i = 0; i < n; i++) { xa[i] = ni(); ya[i] = ni(); xb[i] = ni(); yb[i] = ni(); } Tuple Get(int index, int type) { if (type == 0) { return Tuple.Create(xb[index], yb[index]); } else if (type == 1) { return Tuple.Create(-xa[index], yb[index]); } else if (type == 2) { return Tuple.Create(-xa[index], -ya[index]); } else { return Tuple.Create(xb[index], -ya[index]); } } var x = new int[n]; var y = new int[n]; var ans = new long[n]; for (int t = 0; t < 4; t++) { for (int i = 0; i < n; i++) { var pair = Get(i, t); x[i] = pair.Item1; y[i] = pair.Item2; } var sub = Solve(n, x, y); for (int i = 0; i < n; i++) { ans[i] += sub[i]; } } cout.WriteLine(ans.JoinToString("\n")); } private long[] Solve(int n, int[] x, int[] y) { var seg = new SegmentTreeBeats(); seg.Build(new long[20010]); var area = 0L; var res = new long[n]; for (int i = 0; i < n; i++) { seg.RangeUpdateMax(0, x[i], y[i]); var newArea = seg.QuerySum(0, 20010); //new { index = i, x = x[i], y = y[i], area, newArea }.Dump(); res[i] = newArea - area; area = newArea; } return res; } } public class SegmentTreeBeats { private struct Node { public long Max, Max2nd, Min, Min2nd, Sum; public int MaxCount, MinCount; public Node(long value) { Max = Min = value; Max2nd = long.MinValue; Min2nd = long.MaxValue; MaxCount = MinCount = 1; Sum = value; } } private enum OperatorType { None = 0, Set = 1, Add = 2, } private struct Operator { public static readonly Operator None = new Operator(); public OperatorType Type; public long Value; } private Node[] _node; private Operator[] _operators; private int[] _dataNum; private int N; public void Build(IList array) { Build(array.Count, i => array[i]); } public void Build(int n, Func create) { N = 1; while (N < n) { N *= 2; } _node = new Node[2 * N]; _operators = new Operator[2 * N]; _dataNum = new int[2 * N]; for (int i = 0; i < n; i++) { _node[i + N] = new Node(create(i)); _dataNum[i + N] = 1; } for (int i = n; i < N; i++) { _node[i + N] = new Node(0); } for (int i = N - 1; i > 0; i--) { _dataNum[i] = _dataNum[i << 1] + _dataNum[i << 1 | 1]; BottomUp(i); } } private void BottomUp(int k) { Merge(ref _node[k], ref _node[k << 1], ref _node[k << 1 | 1]); } private static void Merge(ref Node node, ref Node child1, ref Node child2) { int cmp; cmp = child1.Max.CompareTo(child2.Max); if (cmp < 0) { node.Max = child2.Max; node.MaxCount = child2.MaxCount; node.Max2nd = Math.Max(child2.Max2nd, child1.Max); } else if (cmp > 0) { node.Max = child1.Max; node.MaxCount = child1.MaxCount; node.Max2nd = Math.Max(child1.Max2nd, child2.Max); } else { node.Max = child1.Max; node.MaxCount = child1.MaxCount + child2.MaxCount; node.Max2nd = Math.Max(child1.Max2nd, child2.Max2nd); } cmp = child1.Min.CompareTo(child2.Min); if (cmp < 0) { node.Min = child1.Min; node.MinCount = child1.MinCount; node.Min2nd = Math.Min(child1.Min2nd, child2.Min); } else if (cmp > 0) { node.Min = child2.Min; node.MinCount = child2.MinCount; node.Min2nd = Math.Min(child2.Min2nd, child1.Min); } else { node.Min = child1.Min; node.MinCount = child1.MinCount + child2.MinCount; node.Min2nd = Math.Min(child1.Min2nd, child2.Min2nd); } node.Sum = child1.Sum + child2.Sum; } private void TopDown(int k) { int c1 = k << 1; int c2 = c1 | 1; if (_operators[k].Type != OperatorType.None) { Apply(c1, ref _node[c1], _operators[k]); Apply(c2, ref _node[c2], _operators[k]); _operators[k] = Operator.None; } long kmax = _node[k].Max; long kmin = _node[k].Min; if (kmax < _node[c1].Max) { UpdateNodeMax(ref _node[c1], kmax); } if (kmax < _node[c2].Max) { UpdateNodeMax(ref _node[c2], kmax); } if (kmin > _node[c1].Min) { UpdateNodeMin(ref _node[c1], kmin); } if (kmin > _node[c2].Min) { UpdateNodeMin(ref _node[c2], kmin); } } private void Apply(int k, ref Node node, Operator @operator) { int dataNum = _dataNum[k]; if (@operator.Type == OperatorType.Set) { node.Max = node.Min = @operator.Value; node.MaxCount = node.MinCount = dataNum; node.Max2nd = long.MinValue; node.Min2nd = long.MaxValue; node.Sum = dataNum * @operator.Value; } else if (@operator.Type == OperatorType.Add) { if (@operator.Value != 0) { node.Max += @operator.Value; node.Min += @operator.Value; if (node.Max2nd != long.MinValue) { node.Max2nd += @operator.Value; } if (node.Min2nd != long.MaxValue) { node.Min2nd += @operator.Value; } node.Sum += dataNum * @operator.Value; } } else { throw new Exception(); } Merge(ref _operators[k], @operator); } private static void Merge(ref Operator current, Operator append) { if (current.Type != OperatorType.None) { if (append.Type == OperatorType.Set) { // add (+set +add) current = append; } else if (current.Type == OperatorType.Set) { // set add (+add) current.Value += append.Value; } else { current.Value += append.Value; } } else { current = append; } } private void ChangeApply(int begin, int end, Operator @operator) { Action apply = null; apply = (k, l, r) => { if (r <= begin || end <= l) { return; } if (begin <= l && r <= end) { Apply(k, ref _node[k], @operator); return; } int mid = (l + r) >> 1; TopDown(k); apply(k << 1 | 0, l, mid); apply(k << 1 | 1, mid, r); BottomUp(k); }; apply(1, 0, N); } private void ChangeApply(int begin, int end, long value, Func breakCondition, Func tagCondition, Action tag) { Action apply = null; apply = (k, l, r) => { if (r <= begin || end <= l || breakCondition(k, value)) { return; } if (begin <= l && r <= end && tagCondition(k, value)) { tag(k, value); return; } int mid = (l + r) >> 1; TopDown(k); apply(k << 1 | 0, l, mid); apply(k << 1 | 1, mid, r); BottomUp(k); }; apply(1, 0, N); } private void UpdateNodeMin(int k, long value) { UpdateNodeMin(ref _node[k], value); } private static void UpdateNodeMin(ref Node node, long value) { node.Sum += (value - node.Min) * node.MinCount; if (node.Min == node.Max) { node.Min = node.Max = value; } else if (node.Min == node.Max2nd) { node.Min = node.Max2nd = value; } else { node.Min = value; } } private void UpdateNodeMax(int k, long value) { UpdateNodeMax(ref _node[k], value); } private static void UpdateNodeMax(ref Node node, long value) { node.Sum += (value - node.Max) * node.MaxCount; if (node.Max == node.Min) { node.Max = node.Min = value; } else if (node.Max == node.Min2nd) { node.Max = node.Min2nd = value; } else { node.Max = value; } } /// /// a[i] = value where i in [begin,end) /// public void RangeSet(int begin, int end, long value) { ChangeApply(begin, end, new Operator { Type = OperatorType.Set, Value = value }); } /// /// a[i] += value where i in [begin,end) /// public void RangeAdd(int begin, int end, long value) { ChangeApply(begin, end, new Operator { Type = OperatorType.Add, Value = value }); } /// /// a[i] = Min(a[i], value) where i in [begin,end) /// public void RangeUpdateMin(int begin, int end, long value) { ChangeApply(begin, end, value, (k, v) => _node[k].Max <= value, (k, v) => _node[k].Max2nd < value, UpdateNodeMax ); } /// /// a[i] = Max(a[i], value) where i in [begin,end) /// public void RangeUpdateMax(int begin, int end, long value) { ChangeApply(begin, end, value, (k, v) => value <= _node[k].Min, (k, v) => value < _node[k].Min2nd, UpdateNodeMin ); } public long QueryMin(int begin, int end) { Func query = null; query = (k, l, r) => { if (r <= begin || end <= l) { return long.MaxValue; } if (begin <= l && r <= end) { return _node[k].Min; } int mid = (l + r) >> 1; TopDown(k); long lv = query(k << 1 | 0, l, mid); long rv = query(k << 1 | 1, mid, r); return Math.Min(lv, rv); }; return query(1, 0, N); } public long QueryMax(int begin, int end) { Func query = null; query = (k, l, r) => { if (r <= begin || end <= l) { return long.MinValue; } if (begin <= l && r <= end) { return _node[k].Max; } int mid = (l + r) >> 1; TopDown(k); long lv = query(k << 1 | 0, l, mid); long rv = query(k << 1 | 1, mid, r); return Math.Max(lv, rv); }; return query(1, 0, N); } public long QuerySum(int begin, int end) { Func query = null; query = (k, l, r) => { if (r <= begin || end <= l) { return 0; } if (begin <= l && r <= end) { return _node[k].Sum; } int mid = (l + r) >> 1; TopDown(k); long lv = query(k << 1 | 0, l, mid); long rv = query(k << 1 | 1, mid, r); return lv + rv; }; return query(1, 0, N); } } // PREWRITEN CODE BEGINS FROM HERE static public class StringExtensions { static public string JoinToString(this IEnumerable source, string separator = " ") { return string.Join(separator, source); } } internal partial class Solver : Scanner { public static void Main() { #if LOCAL byte[] inputBuffer = new byte[1000000]; var inputStream = Console.OpenStandardInput(inputBuffer.Length); using (var reader = new StreamReader(inputStream, Console.InputEncoding, false, inputBuffer.Length)) { Console.SetIn(reader); new Solver(Console.In, Console.Out).Run(); } #else Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); new Solver(Console.In, Console.Out).Run(); Console.Out.Flush(); #endif } #pragma warning disable IDE0052 private readonly TextReader cin; private readonly TextWriter cout; private readonly TextWriter cerr; #pragma warning restore IDE0052 public Solver(TextReader reader, TextWriter writer) : base(reader) { cin = reader; cout = writer; cerr = Console.Error; } public Solver(string input, TextWriter writer) : this(new StringReader(input), writer) { } #pragma warning disable IDE1006 #pragma warning disable IDE0051 private int ni() { return NextInt(); } private int[] ni(int n) { return NextIntArray(n); } private long nl() { return NextLong(); } private long[] nl(int n) { return NextLongArray(n); } private double nd() { return NextDouble(); } private double[] nd(int n) { return NextDoubleArray(n); } private string ns() { return Next(); } private string[] ns(int n) { return NextArray(n); } #pragma warning restore IDE1006 #pragma warning restore IDE0051 } internal static class LinqPadExtension { [Conditional("DEBUG")] public static void Dump(this T obj) { #if DEBUG LINQPad.Extensions.Dump(obj); #endif } } public class Scanner { private readonly TextReader Reader; private readonly CultureInfo ci = CultureInfo.InvariantCulture; private readonly char[] buffer = new char[2 * 1024]; private int cursor = 0, length = 0; private string Token; private readonly StringBuilder sb = new StringBuilder(1024); public Scanner() : this(Console.In) { } public Scanner(TextReader reader) { Reader = reader; } public int NextInt() { return checked((int)NextLong()); } public long NextLong() { var s = Next(); long r = 0; int i = 0; bool negative = false; if (s[i] == '-') { negative = true; i++; } for (; i < s.Length; i++) { r = r * 10 + (s[i] - '0'); #if DEBUG if (!char.IsDigit(s[i])) throw new FormatException(); #endif } return negative ? -r : r; } public double NextDouble() { return double.Parse(Next(), ci); } public string[] NextArray(int size) { string[] array = new string[size]; for (int i = 0; i < size; i++) { array[i] = Next(); } return array; } public int[] NextIntArray(int size) { int[] array = new int[size]; for (int i = 0; i < size; i++) { array[i] = NextInt(); } return array; } public long[] NextLongArray(int size) { long[] array = new long[size]; for (int i = 0; i < size; i++) { array[i] = NextLong(); } return array; } public double[] NextDoubleArray(int size) { double[] array = new double[size]; for (int i = 0; i < size; i++) { array[i] = NextDouble(); } return array; } public string Next() { if (Token == null) { if (!StockToken()) { throw new Exception(); } } var token = Token; Token = null; return token; } public bool HasNext() { if (Token != null) { return true; } return StockToken(); } private bool StockToken() { while (true) { sb.Clear(); while (true) { if (cursor >= length) { cursor = 0; if ((length = Reader.Read(buffer, 0, buffer.Length)) <= 0) { break; } } var c = buffer[cursor++]; if (33 <= c && c <= 126) { sb.Append(c); } else { if (sb.Length > 0) break; } } if (sb.Length > 0) { Token = sb.ToString(); return true; } return false; } } }