malahovknst

Untitled

Mar 9th, 2022
982
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.79 KB | None | 0 0
  1. using System;
  2.  
  3. public class MainClass
  4. {
  5.     class Program
  6.     {
  7.         static void Main()
  8.         {            
  9.             string[] input = Console.ReadLine().Split(' ');
  10.             int n = int.Parse(input[0]);
  11.  
  12.             AVLTree tree = new AVLTree();
  13.  
  14.             for (int i = 0; i < n; i++)
  15.             {
  16.                 input = Console.ReadLine().Split(' ');
  17.                 long value = long.Parse(input[1]);
  18.  
  19.                 switch (input[0])
  20.                 {
  21.                     case "?":
  22.                         Console.WriteLine(tree.Find(tree.GetModifiedValue(value)) != null ? "Found" : "Not found");
  23.                         //Console.WriteLine(tree.Find(value) != null ? "Found" : "Not found");
  24.                         break;
  25.  
  26.                     case "+":
  27.                         tree.Add(tree.GetModifiedValue(value));
  28.                         //tree.Add(value);
  29.                         break;
  30.  
  31.                     case "-":
  32.                         tree.Remove(tree.GetModifiedValue(value));
  33.                         //tree.Remove(value);
  34.                         break;
  35.  
  36.                     case "s":
  37.                         tree.Sum(tree.GetModifiedValue(value), tree.GetModifiedValue(long.Parse(input[2])));
  38.                         break;
  39.                 }
  40.             }
  41.  
  42.             Console.Read();
  43.         }
  44.  
  45.         public class AVLTree
  46.         {
  47.             public Node Root;
  48.             public int Size;
  49.             private long _sum;
  50.  
  51.             public AVLTree()
  52.             {
  53.                 Size = 0;
  54.                 _sum = 0;
  55.             }
  56.  
  57.             public long GetModifiedValue(long value)
  58.             {
  59.                 return (value + _sum) % 1000000001;
  60.             }            
  61.  
  62.             private void ShowTree()
  63.             {
  64.                 Console.WriteLine("Tree: ");
  65.                 PreOrderTraverse(Root);
  66.             }
  67.  
  68.             private void PreOrderTraverse(Node node)
  69.             {
  70.                 if (node == null) return;
  71.  
  72.                 Console.Write(node.Value + "(" + node.Height + "):" + node.Sum + " ");
  73.                 PreOrderTraverse(node.Left);
  74.                 PreOrderTraverse(node.Right);
  75.             }
  76.  
  77.             public void Add(long value)
  78.             {                
  79.                 Node node = new Node(value);
  80.                 this.AddNode(node); //добавление ноды с просеиванием вниз                
  81.  
  82.                 //балансировка дерева снизу вверх, начиная с родителя добавленной ноды
  83.                 Node parent = node.Parent;
  84.                 while (parent != null)
  85.                 {
  86.                     int balance = parent.GetBalance();
  87.  
  88.                     if (Math.Abs(balance) == 2) //-2 или 2 = разбалансировано                    
  89.                         BalanceAt(parent, balance);                    
  90.                     else
  91.                         parent.RecalculateHeightAndSum(); //если не было балансировки(где пересчитывается высота с суммой родителя), то нужно отдельно запустить пересчет высоты с суммой
  92.  
  93.                     parent = parent.Parent;
  94.                 }
  95.  
  96.                 //ShowTree();
  97.             }
  98.  
  99.             private void AddNode(Node node) //добавление с просеиванием вниз
  100.             {
  101.                 if (Root == null)
  102.                 {
  103.                     Root = node;
  104.                     Size++;
  105.                 }
  106.                 else
  107.                 {
  108.                     if (node.Parent == null)
  109.                         node.Parent = Root; //подвешивается к корню
  110.  
  111.                     if (node.Value < node.Parent.Value) //если меньше родителя - влево падает //(в нормальном дереве тут <=, и последнего условия нет, чтоб дуликаты можно было добавлять)
  112.                     {
  113.                         if (node.Parent.Left == null)
  114.                         {
  115.                             node.Parent.Left = node;
  116.                             Size++;
  117.                         }
  118.                         else
  119.                         {
  120.                             node.Parent = node.Parent.Left; //переподвешивается к левому ребенку своего родителя
  121.                             AddNode(node); //просеивает себя дальше
  122.                         }
  123.                     }
  124.                     else if (node.Value > node.Parent.Value) //если больше родителя - вправо падает
  125.                     {
  126.                         if (node.Parent.Right == null)
  127.                         {
  128.                             node.Parent.Right = node;
  129.                             Size++;
  130.                         }
  131.                         else
  132.                         {
  133.                             node.Parent = node.Parent.Right; //переподвешивается к правому ребенку своего родителя
  134.                             AddNode(node); //просеивает себя дальше
  135.                         }
  136.                     }
  137.                     else //уже есть такая нода, эту отбрасываем
  138.                     {
  139.                         node.Parent = null;
  140.                         return;
  141.                     }
  142.                 }
  143.             }
  144.  
  145.             private void BalanceAt(Node node, int balance)
  146.             {
  147.                 if (balance == 2) //справа перевес
  148.                 {
  149.                     int rightBalance = node.Right.GetBalance();
  150.  
  151.                     if (rightBalance == 1 || rightBalance == 0)
  152.                     {
  153.                         //вращение влево вокруг текущей ноды
  154.                         RotateLeft(node);
  155.                     }
  156.                     else if (rightBalance == -1)
  157.                     {
  158.                         //вращение вправо вокруг правой ноды
  159.                         RotateRight(node.Right);
  160.  
  161.                         //вращение влево вокруг текущей ноды
  162.                         RotateLeft(node);
  163.                     }
  164.                 }
  165.                 else if (balance == -2) //слева перевес
  166.                 {
  167.                     int leftBalance = node.Left.GetBalance();
  168.                     if (leftBalance == 1)
  169.                     {
  170.                         //вращение влево вокруг левой ноды
  171.                         RotateLeft(node.Left);
  172.  
  173.                         //вращение вправо вокруг текущей ноды
  174.                         RotateRight(node);
  175.                     }
  176.                     else if (leftBalance == -1 || leftBalance == 0)
  177.                     {
  178.                         //вращение вправо вокруг текущей ноды
  179.                         RotateRight(node);
  180.                     }
  181.                 }
  182.             }            
  183.  
  184.             public void Remove(long value)
  185.             {
  186.                 Node node = Find(value);
  187.                 if (node == null) return;                
  188.  
  189.                 RemoveNode(node);                
  190.  
  191.                 //ShowTree();
  192.             }
  193.  
  194.             private void RemoveNode(Node node)
  195.             {
  196.                 Node parent = node.Parent; //перед удалением ноды, запоминаем её родителя, чтоб балансировку там проверять
  197.                 bool wasRoot = Root == node;
  198.  
  199.                 if (Size == 1) //удаление корня
  200.                 {
  201.                     Root = null;
  202.                     Size--;
  203.                 }
  204.                 else if (node.Left == null && node.Right == null) //если нет детей
  205.                 {
  206.                     if (node.Parent != null)
  207.                     {
  208.                         if (node.Parent.Left == node)
  209.                             node.Parent.Left = null;
  210.                         else
  211.                             node.Parent.Right = null;
  212.  
  213.                         node.Parent = null;
  214.                         Size--;
  215.                     }
  216.                 }
  217.                 else if (node.Left != null && node.Right != null) //есть 2 детей
  218.                 {                    
  219.                     Node successorNode = node.Left;
  220.  
  221.                     while (successorNode.Right != null)
  222.                         successorNode = successorNode.Right;
  223.  
  224.                     node.Value = successorNode.Value;
  225.                     //node.RecalculateHeightAndSum();
  226.  
  227.                     RemoveNode(successorNode);//рекурсия
  228.                 }
  229.                 else //есть 1 ребенок
  230.                 {
  231.                     if (node.Left != null)
  232.                     {                        
  233.                         node.Left.Parent = node.Parent;
  234.  
  235.                         if (wasRoot)
  236.                             Root = node.Left;
  237.  
  238.                         if (node.Parent != null)
  239.                         {
  240.                             if (node.Parent.Left == node)
  241.                                 node.Parent.Left = node.Left;
  242.                             else
  243.                                 node.Parent.Right = node.Left;
  244.                         }
  245.                     }
  246.                     else
  247.                     {
  248.                         node.Right.Parent = node.Parent;
  249.  
  250.                         if (wasRoot)
  251.                             Root = node.Right;
  252.  
  253.                         if (node.Parent != null)
  254.                         {
  255.                             if (node.Parent.Left == node)
  256.                                 node.Parent.Left = node.Right;
  257.                             else
  258.                                 node.Parent.Right = node.Right;
  259.                         }
  260.                     }
  261.  
  262.                     node.Parent = null;
  263.                     node.Left = null;
  264.                     node.Right = null;
  265.                     Size--;
  266.                 }
  267.  
  268.                 //балансировка дерева, если высота изменилась
  269.                 while (parent != null)
  270.                 {
  271.                     int balance = parent.GetBalance();
  272.  
  273.                     /*if (Math.Abs(balance) != 2)
  274.                         parent.RecalculateHeightAndSum(); //если не будет балансировки(где пересчитывается высота с суммой родителя), то нужно отдельно запустить пересчет высоты с суммой
  275.  
  276.                     if (Math.Abs(balance) == 1) //1, -1                                            
  277.                         break;
  278.                     else if (Math.Abs(balance) == 2) //2, -2
  279.                         BalanceAt(parent, balance);*/
  280.                    
  281.                     if (Math.Abs(balance) == 2)
  282.                         BalanceAt(parent, balance);
  283.                     else
  284.                         parent.RecalculateHeightAndSum();
  285.  
  286.                     parent = parent.Parent;
  287.                 }
  288.             }
  289.  
  290.             public void Sum(long l, long r)
  291.             {
  292.                 long lMin, lMax, rMin, rMax;
  293.  
  294.                 FindLessAndGreaterSums(l, out lMin, out lMax);
  295.                 FindLessAndGreaterSums(r, out rMin, out rMax);
  296.  
  297.                 //Console.WriteLine("l = " + l + "(" + lMin + ":" + lMax + "); r = " + r + "(" + rMin + ":" + rMax + ")");
  298.  
  299.                 _sum = Root != null ? Root.Sum - lMin - rMax : 0;
  300.                 Console.WriteLine(_sum);
  301.             }
  302.  
  303.             private void FindLessAndGreaterSums(long value, out long sumLess, out long sumGreater)
  304.             {
  305.                 bool found = false;
  306.                 sumLess = 0;
  307.                 sumGreater = 0;
  308.  
  309.                 Node node = Root;
  310.  
  311.                 while (node != null)
  312.                 {
  313.                     if (value < node.Value)
  314.                     {
  315.                         if (node.Right != null)                        
  316.                             sumGreater += node.Right.Sum;
  317.                         sumGreater += node.Value;
  318.                         node = node.Left;
  319.                     }
  320.                     else if (value > node.Value)
  321.                     {
  322.                         if (node.Left != null)
  323.                             sumLess += node.Left.Sum;
  324.                         sumLess += node.Value;
  325.                         node = node.Right;
  326.                     }
  327.                     else
  328.                     {
  329.                         found = true;
  330.                         break;
  331.                     }
  332.                 }
  333.  
  334.                 if (found)
  335.                 {
  336.                     if (node.Left != null)
  337.                         sumLess += node.Left.Sum;
  338.                     if (node.Right != null)
  339.                         sumGreater += node.Right.Sum;
  340.                 }
  341.             }
  342.  
  343.             public Node Find(long value)
  344.             {
  345.                 Node node = Root;
  346.  
  347.                 while (node != null)
  348.                 {
  349.                     if (node.Value == value)
  350.                         return node;
  351.                     else
  352.                         node = value >= node.Value ? node.Right : node.Left;
  353.                 }
  354.  
  355.                 return null;
  356.             }
  357.  
  358.             private void RotateLeft(Node node)
  359.             {
  360.                 if (node == null || node.Right == null) return;
  361.  
  362.                 Node pivot = node.Right;                
  363.  
  364.                 Node parent = node.Parent;
  365.                 bool isLeftChild = (parent != null) && parent.Left == node;
  366.                 bool makeTreeRoot = Root == node; //нужно обновить корень
  367.  
  368.                 //Вращение
  369.                 node.Right = pivot.Left;
  370.                 pivot.Left = node;
  371.  
  372.                 node.Parent = pivot;
  373.                 pivot.Parent = parent;
  374.  
  375.                 if (node.Right != null)
  376.                     node.Right.Parent = node;
  377.  
  378.                 if (makeTreeRoot)
  379.                     Root = pivot; //обновление корня дерева
  380.  
  381.                 if (isLeftChild)
  382.                     parent.Left = pivot;
  383.                 else if (parent != null)
  384.                     parent.Right = pivot;
  385.  
  386.                 node.RecalculateHeightAndSum();
  387.                 pivot.RecalculateHeightAndSum();
  388.             }
  389.  
  390.             private void RotateRight(Node node)
  391.             {
  392.                 if (node == null || node.Left == null) return;
  393.  
  394.                 Node pivot = node.Left;
  395.  
  396.                 Node parent = node.Parent;
  397.                 bool isLeftChild = (parent != null) && parent.Left == node;
  398.                 bool makeTreeRoot = Root == node; //нужно обновить корень
  399.  
  400.                 //Вращение
  401.                 node.Left = pivot.Right;
  402.                 pivot.Right = node;
  403.  
  404.                 node.Parent = pivot;
  405.                 pivot.Parent = parent;
  406.  
  407.                 if (node.Left != null)
  408.                     node.Left.Parent = node;
  409.  
  410.                 if (makeTreeRoot)
  411.                     Root = pivot; //обновление корня дерева
  412.  
  413.                 if (isLeftChild)
  414.                     parent.Left = pivot;
  415.                 else if (parent != null)
  416.                     parent.Right = pivot;
  417.  
  418.                 node.RecalculateHeightAndSum();
  419.                 pivot.RecalculateHeightAndSum();
  420.             }
  421.  
  422.             public class Node
  423.             {
  424.                 public long Value;
  425.                 public Node Parent;
  426.                 public Node Left;
  427.                 public Node Right;
  428.                 public long Sum; //сумма всех значений поддерева с корнем в этой ноде (минимально равна значению в ноде)
  429.                 public int Height; //высота поддерева с корнем в этой ноде (минимально равна 1)
  430.  
  431.                 public Node(long value)
  432.                 {
  433.                     Value = value;
  434.                     Sum = value;
  435.                     Height = 1;
  436.                 }
  437.  
  438.                 public void RecalculateHeightAndSum()
  439.                 {                    
  440.                     Height = 1 + Math.Max(Right != null ? Right.Height : 0, Left != null ? Left.Height : 0);
  441.                     Sum = Value + (Right != null ? Right.Sum : 0) + (Left != null ? Left.Sum : 0);
  442.                 }
  443.  
  444.                 public int GetBalance() => (Right != null ? Right.Height : 0) - (Left != null ? Left.Height : 0);
  445.             }
  446.         }
  447.     }
  448. }
Advertisement
Add Comment
Please, Sign In to add comment