【动态规划】【滑动窗口】【C++算法】 629K 个逆序对数组

简介: 【动态规划】【滑动窗口】【C++算法】 629K 个逆序对数组

作者推荐

视频算法专题

本文涉及知识点

动态规划汇总

C++算法:滑动窗口总结

LeetCode629: K 个逆序对数组

逆序对的定义如下:对于数组 nums 的第 i 个和第 j 个元素,如果满足 0 <= i < j < nums.length 且 nums[i] > nums[j],则其为一个逆序对;否则不是。

给你两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个 逆序对 的不同的数组的个数。由于答案可能很大,只需要返回对 109 + 7 取余的结果。

示例 1:

输入:n = 3, k = 0

输出:1

解释:

只有数组 [1,2,3] 包含了从1到3的整数并且正好拥有 0 个逆序对。

示例 2:

输入:n = 3, k = 1

输出:2

解释:

数组 [1,3,2] 和 [2,1,3] 都有 1 个逆序对。

提示:

1 <= n <= 1000

0 <= k <= 1000

动态规划

** 空间复杂度**: O(n)

时间复杂度😮(n2)

动态规划的状态表示:pre[i]表示1到j-1的排列中,逆数对数量为i的数量。dp[i]表示1到j的排列中,逆数对的数量。 i 取值范围[0,1000]

动态规划的转移方程: 假定某个1到j-1 的排列,逆数对为x。插入j后,除j外的顺序不边,也就是除j外,不会产生新的逆数对。当然也不会减少逆数对。那如果将j插入到最后,逆序数不变。插入到倒数第一之前,逆数对+1。。。插入到最前面,逆序对+j-1。换过说法:

dp[i] = Sum( i − j , i ] k ^{k}_{(i-j,i]}(ij,i]kpre[k]。 可以利用滑动窗口求和。

动态规划的初始状态: pre[0]=0

动态规划的填表顺序: j 从小到大,i从小到大。

动态规划的返回值:pre[k]

代码

使用到的类库

template<int MOD = 1000000007>
class C1097Int
{
public:
  C1097Int(long long llData = 0) :m_iData(llData% MOD)
  {
  }
  C1097Int  operator+(const C1097Int& o)const
  {
    return C1097Int(((long long)m_iData + o.m_iData) % MOD);
  }
  C1097Int& operator+=(const C1097Int& o)
  {
    m_iData = ((long long)m_iData + o.m_iData) % MOD;
    return *this;
  }
  C1097Int& operator-=(const C1097Int& o)
  {
    m_iData = (m_iData + MOD - o.m_iData) % MOD;
    return *this;
  }
  C1097Int  operator-(const C1097Int& o)
  {
    return C1097Int((m_iData + MOD - o.m_iData) % MOD);
  }
  C1097Int  operator*(const C1097Int& o)const
  {
    return((long long)m_iData * o.m_iData) % MOD;
  }
  C1097Int& operator*=(const C1097Int& o)
  {
    m_iData = ((long long)m_iData * o.m_iData) % MOD;
    return *this;
  }
  bool operator<(const C1097Int& o)const
  {
    return m_iData < o.m_iData;
  }
  C1097Int pow(long long n)const
  {
    C1097Int iRet = 1, iCur = *this;
    while (n)
    {
      if (n & 1)
      {
        iRet *= iCur;
      }
      iCur *= iCur;
      n >>= 1;
    }
    return iRet;
  }
  C1097Int PowNegative1()const
  {
    return pow(MOD - 2);
  }
  int ToInt()const
  {
    return m_iData;
  }
private:
  int m_iData = 0;;
};

核心代码

class Solution {
public:
  int kInversePairs(int n, int k) {
    vector<C1097Int<>> pre(1001) ;
    pre[0] = 1;
    for (int j = 2; j <= n; j++)
    {
      vector<C1097Int<>> dp(1001);
      C1097Int<> iSum = 0;
      for (int i = 0; i < pre.size(); i++)
      {
        iSum += pre[i];
        if (i - j >= 0)
        {
          iSum -= pre[i - j];
        }
        dp[i] = iSum;
      }
      pre.swap(dp);
    }
    return pre[k].ToInt();
  }
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
  assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
  if (v1.size() != v2.size())
  {
    assert(false);
    return;
  }
  for (int i = 0; i < v1.size(); i++)
  {
    Assert(v1[i], v2[i]);
  }
}
int main()
{
  int n,k;
  {
    Solution sln;
    n = 3, k = 0;
    auto res = sln.kInversePairs(n, k);
    Assert(1, res);
  }
  {
    Solution sln;
    n = 3, k = 1;
    auto res = sln.kInversePairs(n, k);
    Assert(2, res);
  }
  {
    Solution sln;
    n = 1000, k = 1000;
    auto res = sln.kInversePairs(n, k);
    Assert(663677020, res);
  }
}

2023年1月版

class CBigMath

{

public:

static void AddAssignment(int* dst, const int& iSrc)

{

*dst = (*dst + iSrc) % s_iMod;

}

static void AddAssignment(int* dst, const int& iSrc, const int& iSrc1)
 {
   *dst = (*dst + iSrc) % s_iMod;
   *dst = (*dst + iSrc1) % s_iMod;
 }
 static void AddAssignment(int* dst, const int& iSrc, const int& iSrc1, const int& iSrc2)
 {
   *dst = (*dst + iSrc) % s_iMod;
   *dst = (*dst + iSrc1) % s_iMod;
   *dst = (*dst + iSrc2) % s_iMod;
 }
 static void SubAssignment(int* dst, const int& iSrc)
 {
   *dst = (s_iMod - iSrc + *dst) % s_iMod;
 }
 static int Add(const int& iAdd1, const int& iAdd2)
 {
   return (iAdd1 + iAdd2) % s_iMod;
 }
 static int Mul(const int& i1, const int& i2)
 {
   return((long long)i1 *i2) % s_iMod;
 }

private:

static const int s_iMod = 1000000007;

};

class Solution {

public:

int kInversePairs(int n, int k) {

vector preDp(k + 1);

preDp[0] = 1;

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

{

vector dp(k+1 );

for (int j = 0; j < dp.size(); j++)

{

if (j < preDp.size())

{

CBigMath::AddAssignment(&dp[j], preDp[j]);

}

if (j > 0)

{

CBigMath::AddAssignment(&dp[j], dp[j - 1]);

}

if ( j - i >= 0)

{

int iMod = 1000000007;

CBigMath::AddAssignment(&dp[j], iMod - preDp[j - i]);

}

}

preDp.swap(dp);

}

return k >= preDp.size() ? 0 : preDp[k];

}

};

2023年6月

using namespace std;

template

void OutToConsoleInner(const vector& vec,const string& strSep = " ")

{

for (int i = 0; i < vec.size(); i++)

{

if (0 != i%25)

{

std::cout << strSep.c_str();

}

std::cout << setw(3) << setfill(’ ') << vec[i];

if (0 == (i+1) % 25)

{

std::cout << std::endl;

}

else if (0 == (i + 1) % 5)

{

std::cout << strSep.c_str();

}

}

}

class CConsole

{

public :

template<class T>
static void Out(const vector<T>& vec, const string& strColSep = " ", const string& strRowSep = "\r\n")
{
  OutToConsoleInner(vec, strColSep);
  std::cout << strRowSep.c_str();
}
template<class T>
static void Out(const vector<vector<T>>& matrix, const string& strColSep = " ", const string& strRowSep = "\r\n")
{
  for (int i = 0; i < matrix.size(); i++)
  {
    OutToConsoleInner(matrix[i], strColSep);
    std::cout << strRowSep.c_str();
  }
}
template<class T>
static void Out(const std::map<T, std::vector<int> >& mTopPointToPoints, const string& strColSep = " ", const string& strRowSep = "\r\n")
{
  for (auto kv : mTopPointToPoints)
  {
    std::cout << kv.first << ":";
    OutToConsoleInner(kv.second, strColSep);
    std::cout << strRowSep.c_str();
  }
}
static void Out(const  std::string& t, const string& strColSep = " ", const string& strRowSep = "\r\n")
{
  std::cout << t.c_str() << strColSep.c_str();
}
template<class T  >
static void Out(const T& t, const string& strColSep = " ", const string& strRowSep = "\r\n")
{
  std::cout << t << strColSep.c_str();
}

};

void GenetateSum(vector& sums, const vector& nums)

{

sums.push_back(0);

for (int i = 0; i < nums.size(); i++)

{

sums.push_back(nums[i] + sums[i]);

}

}

//[iBegin,iEnd]之和

long long Total(int iBegin,int iEnd)

{

return (long long)(iBegin + iEnd)*(iEnd - iBegin + 1) / 2;

}

class CLadderhlp

{

public:

CLadderhlp( int ladders)

{

m_uLadderNum = ladders;

}

void AddNeedBick(int iNeedBick)

{

if (0 == m_uLadderNum)

{

return;

}

if (m_ladders.size() < m_uLadderNum)

{

m_ladders.push(iNeedBick);

m_iEaqualBicks += iNeedBick;

return;

}

int iTop = m_ladders.top();

if (iTop >= iNeedBick)

{

return;

}

m_iEaqualBicks -= iTop;

m_iEaqualBicks += iNeedBick;

m_ladders.pop();

m_ladders.push(iNeedBick);

}

std::priority_queue<int,vector,std::greater > m_ladders;

unsigned int m_uLadderNum;

long long m_iEaqualBicks = 0;

};

struct CPeo

{

CPeo(string strName, CPeo* pParent=nullptr)

{

m_strName = strName;

m_pParent = pParent;

}

string m_strName;

vector<CPeo*> m_childs;

CPeo* m_pParent = nullptr;

};

class CNeighborTable

{

public:

void Init(const vector<vector>& edges)

{

}
 vector<vector<int>> m_vTable;

};

//通过 x &= (x-1)实现

int bitcount(unsigned x) {

int countx = 0;

while (x) {

countx++;

x &= (x - 1);

}

return countx;

}

int bitcount(unsigned long long x) {

int countx = 0;

while (x) {

countx++;

x &= (x - 1);

}

return countx;

}

class CRange

{

public:

template

CRange(const T& v)

{

m_iBegin = 0;

m_iEnd = v.size();

}

bool In(int iIndex)

{

return (iIndex >= m_iBegin) && (iIndex < m_iEnd);

}

const int End()

{

return m_iEnd;

}

protected:

int m_iBegin;

int m_iEnd;

};

template

class CTrie

{

public:

CTrie() :m_vPChilds(iTypeNum)

{

}
 template<class IT>
 void Add(IT begin, IT end)
 {
   CTrie<iTypeNum, cBegin> * pNode = this;
   for (; begin != end; ++begin)
   {
     pNode = pNode->AddChar(*begin).get();
   }
 }
 template<class IT>
 bool Search(IT begin, IT end)
 {
   if (begin == end)
   {
     return true;
   }
   if ('.' == *begin)
   {
     for (auto& ptr : m_vPChilds)
     {
       if (!ptr)
       {
         continue;
       }
       if (ptr->Search(begin + 1, end))
       {
         return true;
       }
     }
   }
   auto ptr = GetChild(*begin);
   if (nullptr == ptr)
   {
     return false;
   }
   return ptr->Search(begin + 1, end);
 }

protected:

std::shared_ptr AddChar(char ch)

{

if ((ch < cBegin) || (ch >= cBegin + iTypeNum))

{

return nullptr;

}

const int index = ch - cBegin;

auto ptr = m_vPChilds[index];

if (!ptr)

{

m_vPChilds[index] = std::make_shared<CTrie<iTypeNum, cBegin>>();

}

return m_vPChilds[index];

}

std::shared_ptr GetChild(char ch)const

{

if ((ch < cBegin) || (ch >= cBegin + iTypeNum))

{

return nullptr;

}

return m_vPChilds[ch - cBegin];

}

std::vector<std::shared_ptr> m_vPChilds;

};

class CWords

{

public:

void Add(const string& word)

{

m_strStrs.insert(word);

}

bool Search(const string& word)

{

return Search(m_strStrs.begin(), m_strStrs.end(), 0, word.length(), word);

}

protected:

bool Search(std::set::const_iterator begin, std::set::const_iterator end, int iStrBegin, int iStrEnd, const string& str)

{

int i = iStrBegin;

for (; (i < iStrEnd) && (str[i] != ‘.’); i++);

auto it = std::equal_range(begin, end, str, [&iStrBegin, &i](const string& s, const string& sFind)

{

return s.substr(iStrBegin, i - iStrBegin) < sFind.substr(iStrBegin, i - iStrBegin);

});

if (i == iStrBegin)

{

it.first = begin;

it.second = end;

}

if (it.first == it.second)

{

return false;

}

if (i == iStrEnd)

{

return true;

}

if (i + 1 == iStrEnd)

{

return true;

}

string tmp = str;

for (char ch = ‘a’; ch <= ‘z’; ch++)

{

tmp[i] = ch;

auto ij = std::equal_range(it.first, it.second, tmp, [&ch, &i](const string& s, const string& sFind)

{

return s[i] < sFind[i];

});

if (ij.first == ij.second)

{

continue;

}

if (Search(ij.first, ij.second, i + 1, iStrEnd, str))
     {
       return true;
     }
   }
   return false;
 }
 std::set<string> m_strStrs;

};

class WordDictionary {

public:

WordDictionary() {

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

{

m_str[i] = std::make_unique();

}

}

void addWord(string word) {
   m_str[word.length()]->Add(word);
 }
 bool search(string word) {
   return m_str[word.length()]->Search(word);
 }
 std::unique_ptr<CWords> m_str[26];

};

template

class C1097Int

{

public:

C1097Int(long long llData = 0) :m_iData(llData%MOD)

{

}
 C1097Int  operator+(const C1097Int& o)const
 {
   return C1097Int(((long long)m_iData + o.m_iData) % MOD);
 }
 C1097Int&  operator+=(const C1097Int& o)
 {
   m_iData = ((long long)m_iData + o.m_iData) % MOD;
   return *this;
 }
 C1097Int&  operator-=(const C1097Int& o)
 {
   m_iData = (m_iData + MOD - o.m_iData) % MOD;
   return *this;
 }
 C1097Int  operator-(const C1097Int& o)
 {
   return C1097Int((m_iData + MOD - o.m_iData) % MOD);
 }
 C1097Int  operator*(const C1097Int& o)const
 {
   return((long long)m_iData *o.m_iData) % MOD;
 }
 C1097Int&  operator*=(const C1097Int& o)
 {
   m_iData = ((long long)m_iData *o.m_iData) % MOD;
   return *this;
 }
 bool operator<(const C1097Int& o)const
 {
   return m_iData < o.m_iData;
 }
 C1097Int pow( int n)const
 {
   C1097Int iRet = 1, iCur = *this;
  while (n)
  {
    if (n & 1)
    {
      iRet *= iCur;
    }
    iCur *= iCur;
    n >>= 1;
  }
  return iRet;
 }
 C1097Int PowNegative1()const
 {
   return pow(MOD - 2);
 }
 int ToInt()const
 {
   return m_iData;
 }

private:

int m_iData = 0;;

};

template

int operator+(int iData, const C1097Int& int1097)

{

int iRet = int1097.operator+(C1097Int(iData)).ToInt();

return iRet;

}

template

int& operator+=(int& iData, const C1097Int& int1097)

{

iData = int1097.operator+(C1097Int(iData)).ToInt();

return iData;

}

template

int operator*(int iData, const C1097Int& int1097)

{

int iRet = int1097.operator*(C1097Int(iData)).ToInt();

return iRet;

}

template

int& operator*=(int& iData, const C1097Int& int1097)

{

iData = int1097.operator*(C1097Int(iData)).ToInt();

return iData;

}

template

void MinSelf(T* seft, const T& other)

{

*seft = min(*seft, other);

}

template

void MaxSelf(T* seft, const T& other)

{

*seft = max(*seft, other);

}

int GetNotRepeateNum(int len, int iHasSel)

{

if (0 == len)

{

return 1;

}

if ((0 == iHasSel) && (1 == len))

{

return 10;

}

int iRet = 1;

if (iHasSel > 0)

{

for (int tmp = 10 - iHasSel; (tmp >= 2)&& len ; tmp–,len–)

{

iRet *= tmp;

}

}

else

{

iRet *= 9;

len–;

for (int tmp=9; (tmp>=2)&&len; len–,tmp–)

{

iRet *= tmp;

}

}

return iRet;

}

int GCD(int n1, int n2)

{

int t1 = min(n1, n2);

int t2 = max(n1, n2);

if (0 == t1)

{

return t2;

}

return GCD(t2%t1, t1);

}

void CreateMaskVector(vector& v,const int* const p,int n )

{

const int iMaxMaskNum = 1 << n;

v.resize(iMaxMaskNum);

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

{

v[1 << i] = p[i];

}

for (int mask = 1; mask < iMaxMaskNum ; mask++)

{

const int iSubMask = mask&(-mask);

v[mask] = v[iSubMask] + v[mask-iSubMask];

}

}

class CMaxLineTree

{

public:

CMaxLineTree(int iArrSize) :m_iArrSize(iArrSize), m_vData(iArrSize * 4)

{

}
 //iIndex 从0开始
 void Modify( int iIndex, int iValue)
 {
   Modify(1, 1, m_iArrSize, iIndex + 1, iValue);
 }
 //iNeedQueryLeft iNeedQueryRight 从0开始
 int Query(const int iNeedQueryLeft, const int iNeedQueryRight)
 {
   return Query(1, 1, m_iArrSize, iNeedQueryLeft + 1, iNeedQueryRight + 1);
 }

protected:

int Query(const int iTreeNodeIndex, const int iRecordLeft, const int iRecordRight, const int iNeedQueryLeft, const int iNeedQueryRight)

{

if ((iNeedQueryLeft <= iRecordLeft) && (iNeedQueryRight >= iRecordRight))

{

return m_vData[iTreeNodeIndex];

}

const int iMid = (iRecordLeft + iRecordRight) / 2;

int iRet = 0;

if (iNeedQueryLeft <= iMid)

{

iRet = Query(iTreeNodeIndex * 2, iRecordLeft, iMid, iNeedQueryLeft, iNeedQueryRight);

}

if (iNeedQueryRight > iMid)

{

iRet = max(iRet, Query(iTreeNodeIndex * 2 + 1, iMid + 1, iRecordRight, iNeedQueryLeft, iNeedQueryRight));

}

return iRet;

}

void Modify(int iTreeNodeIndex, int iLeft, int iRight, int iIndex, int iValue)

{

if (iLeft == iRight)

{

m_vData[iTreeNodeIndex] = max(m_vData[iTreeNodeIndex],iValue);

return;

}

const int iMid = (iLeft + iRight) / 2;

if (iIndex <= iMid)

{

Modify(iTreeNodeIndex * 2, iLeft, iMid, iIndex, iValue);

}

else

{

Modify(iTreeNodeIndex * 2 + 1, iMid + 1, iRight, iIndex, iValue);

}

m_vData[iTreeNodeIndex] = max(m_vData[iTreeNodeIndex * 2], m_vData[iTreeNodeIndex * 2 + 1]);

}

const int m_iArrSize;

std::vector m_vData;

};

class CMaxLineTreeMap

{

public:

CMaxLineTreeMap(int iArrSize) :m_iArrSize(iArrSize)

{

}
 //iIndex 从0开始
 void Modify(int iIndex, int iValue)
 {
   Modify(1, 1, m_iArrSize, iIndex + 1, iValue);
 }
 //iNeedQueryLeft iNeedQueryRight 从0开始
 int Query(const int iNeedQueryLeft, const int iNeedQueryRight)
 {
   return Query(1, 1, m_iArrSize, iNeedQueryLeft + 1, iNeedQueryRight + 1);
 }

protected:

int Query(const int iTreeNodeIndex, const int iRecordLeft, const int iRecordRight, const int iNeedQueryLeft, const int iNeedQueryRight)

{

if ((iNeedQueryLeft <= iRecordLeft) && (iNeedQueryRight >= iRecordRight))

{

return m_mData[iTreeNodeIndex];

}

const int iMid = (iRecordLeft + iRecordRight) / 2;

int iRet = 0;

if (iNeedQueryLeft <= iMid)

{

iRet = Query(iTreeNodeIndex * 2, iRecordLeft, iMid, iNeedQueryLeft, iNeedQueryRight);

}

if (iNeedQueryRight > iMid)

{

iRet = max(iRet, Query(iTreeNodeIndex * 2 + 1, iMid + 1, iRecordRight, iNeedQueryLeft, iNeedQueryRight));

}

return iRet;

}

void Modify(int iTreeNodeIndex, int iLeft, int iRight, int iIndex, int iValue)

{

if (iLeft == iRight)

{

m_mData[iTreeNodeIndex] = max(m_mData[iTreeNodeIndex], iValue);

return;

}

const int iMid = (iLeft + iRight) / 2;

if (iIndex <= iMid)

{

Modify(iTreeNodeIndex * 2, iLeft, iMid, iIndex, iValue);

}

else

{

Modify(iTreeNodeIndex * 2 + 1, iMid + 1, iRight, iIndex, iValue);

}

m_mData[iTreeNodeIndex] = max(m_mData[iTreeNodeIndex * 2], m_mData[iTreeNodeIndex * 2 + 1]);

}

const int m_iArrSize;

std::unordered_map<int, int> m_mData;

};

template

class CSumLineTree

{

public:

CSumLineTree(int iEleSize) :m_iEleSize(iEleSize), m_vArr(m_iEleSize * 4), m_vChildAdd(m_iEleSize * 4)

{

}
 void Add(int iLeftIndex, int iRightIndex, int iValue)
 {
   Add(1, 1, m_iEleSize, iLeftIndex+1, iRightIndex+1, iValue);
 }
 T Query(int iLeftIndex, int iRightIndex)
 {
   return Query(1, 1, m_iEleSize, iLeftIndex + 1, iRightIndex + 1);
 }

private:

T Query(int iNode, int iDataLeft, int iDataRight, int iOpeLeft, int iOpeRight)

{

if ((iOpeLeft <= iDataLeft) && (iOpeRight >= iDataRight))

{

return m_vArr[iNode];

}

Fresh(iNode, iDataLeft, iDataRight);

const int iMid = iDataLeft + (iDataRight - iDataLeft) / 2;

T ret(0);

if (iMid >= iOpeLeft)

{

ret += Query(iNode * 2, iDataLeft, iMid, iOpeLeft, iOpeRight);

}

if (iMid + 1 <= iOpeRight)

{

ret += Query(iNode * 2 + 1, iMid + 1, iDataRight, iOpeLeft, iOpeRight);

}

return ret;

}

/* 暴力解法

void Add(int iNode, int iDataLeft, int iDataRight, int iOpeLeft, int iOpeRight, int iValue)

{

m_vArr[iNode] += T(iValue)*(min(iDataRight, iOpeRight) - max(iDataLeft, iOpeLeft)+1);

if (iDataLeft == iDataRight)

{

return;

}

const int iMid = iDataLeft + (iDataRight - iDataLeft) / 2;

if (iMid >= iOpeLeft)

{

Add(iNode * 2, iDataLeft, iMid, iOpeLeft, iOpeRight, iValue);

}

if (iMid + 1 <= iOpeRight)

{

Add(iNode * 2 + 1, iMid + 1, iDataRight, iOpeLeft, iOpeRight, iValue);

}

}

/
void Fresh(int iNode, int iDataLeft, int iDataRight)
{
const int iMid = iDataLeft + (iDataRight - iDataLeft) / 2;
if (m_vChildAdd[iNode] != 0)
{
Add(iNode * 2, iDataLeft, iMid, iDataLeft, iMid, m_vChildAdd[iNode]);
Add(iNode * 2 + 1, iMid + 1, iDataRight, iMid + 1, iDataRight, m_vChildAdd[iNode]);
m_vChildAdd[iNode] = 0;
}
}
//懒惰法
void Add(int iNode, int iDataLeft, int iDataRight, int iOpeLeft, int iOpeRight, int iValue)
{
m_vArr[iNode] += T(iValue)
(min(iDataRight, iOpeRight) - max(iDataLeft, iOpeLeft) + 1);

if ((iOpeLeft <= iDataLeft) && (iOpeRight >= iDataRight))

{

m_vChildAdd[iNode] += T(iValue);

return;

}

Fresh(iNode,iDataLeft,iDataRight);
   const int iMid = iDataLeft + (iDataRight - iDataLeft) / 2;
   if (iMid >= iOpeLeft)
   {
     Add(iNode * 2, iDataLeft, iMid, iOpeLeft, iOpeRight, iValue);
   }
   if (iMid + 1 <= iOpeRight)
   {
     Add(iNode * 2 + 1, iMid + 1, iDataRight, iOpeLeft, iOpeRight, iValue);
   }
 }
 const int m_iEleSize;
 vector<T> m_vArr;
 vector<int> m_vChildAdd;

};

template

class CTreeArr

{

public:

CTreeArr(int iSize) :m_vData(iSize+1)

{

}
 void Add(int index, T value)
 {
   index++;
   while (index < m_vData.size())
   {
     m_vData[index] += value;
     index += index&(-index);
   }
 }
 T Sum(int index)
 {
   index++;
   T ret = 0;
   while (index )
   {
     ret += m_vData[index];
     index -= index&(-index);
   }
   return ret;
 }
 T Get(int index)
 {
   return Sum(index) - Sum(index - 1);
 }

private:

vector m_vData;

};

//iCodeNum 必须大于等于可能的字符数

template

class CHashStr {

public:

CHashStr(string s, int iCodeNum, int iCodeBegin = 1, char chBegin = ‘a’) {

m_c = s.length();

m_vP.resize(m_c + 1);

m_vP[0] = 1;

m_vHash.resize(m_c + 1);

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

{

const int P = iCodeBegin + iCodeNum;

m_vHash[i + 1] = m_vHash[i] * P + s[i] - chBegin + iCodeBegin;

m_vP[i + 1] = m_vP[i] * P;

}

}

int GetHash(int left, int right)

{

return ( m_vHash[right + 1] - m_vHash[left] * m_vP[right - left + 1]).ToInt();

}

inline int GetHash(int right)

{

return m_vHash[right + 1].ToInt();

}

int m_c;

vector<C1097Int> m_vP;

vector<C1097Int> m_vHash;

};

template

class C2HashStr

{

public:

C2HashStr(string s) {

m_pHash1 = std::make_unique<CHashStr<>>(s, 26);

m_pHash2 = std::make_unique < CHashStr>(s, 27, 0);

}

long long GetHash(int left, int right)
 {
   return (long long)m_pHash1->GetHash(left, right)*(MOD2 + 1) + m_pHash2->GetHash(left, right);
 }
 long long GetHash( int right)
 {
   return (long long)m_pHash1->GetHash( right)*(MOD2 + 1) + m_pHash2->GetHash( right);
 }

private:

std::unique_ptr<CHashStr<>> m_pHash1;

std::unique_ptr<CHashStr> m_pHash2;

};

template

class CDynaHashStr {

public:

CDynaHashStr(int iCodeNum, int iCodeBegin = 1, char chBegin = ‘a’) :m_iUnit(iCodeNum + iCodeBegin), m_iP(1), m_iBegin(iCodeBegin - chBegin)

{

}
 inline void push_back(const char& ch)
 {
  const int iNum = ch + m_iBegin;
  m_iHash *= m_iUnit;
  m_iHash += iNum;
  m_iP *= m_iUnit;
 }
 inline void push_front(const char& ch)
 {
   const int iNum = ch + m_iBegin;
   m_iHash +=  m_iP*iNum;
   m_iP *= m_iUnit;
 }
 inline int GetHash() const
 {
   return m_iHash;
 }
 const int m_iUnit;
 const int m_iBegin;
 C1097Int<MOD> m_iHash;
 C1097Int<MOD> m_iP;

};

template

class C2DynaHashStr {

public:

C2DynaHashStr(int iCodeNum, int iCodeBegin = 1, char chBegin = ‘a’)

{

m_pHash1 = new CDynaHashStr<>(iCodeNum, iCodeBegin, chBegin);

m_pHash2 = new CDynaHashStr(iCodeNum, iCodeBegin, chBegin);

}

~C2DynaHashStr()

{

delete m_pHash1;

delete m_pHash2;

}

inline void push_back(const char& ch)

{

m_pHash1->push_back(ch);

m_pHash2->push_back(ch);

}

inline void push_front(const char& ch)

{

m_pHash1->push_front(ch);

m_pHash2->push_front(ch);

}

long long Hash()const

{

return (long long)MOD2m_pHash1->m_iHash.ToInt() + m_pHash2->m_iHash.ToInt();
}
bool operator==(const C2DynaHashStr& other) const
{
return (m_pHash1->m_iHash.ToInt() == other.m_pHash1->m_iHash.ToInt()) && (m_pHash2->m_iHash.ToInt() == other.m_pHash2->m_iHash.ToInt());
}
CDynaHashStr<>
m_pHash1;

CDynaHashStr* m_pHash2 ;

};

namespace NSort

{

template

bool SortVecVec(const vector& v1, const vector& v2)

{

return v1[ArrIndex] < v2[ArrIndex];

};

}

namespace NCmp

{

template

bool Less(const std::pair<Class1, int>& p, Class1 iData)

{

return p.first < iData;

}

template<class Class1>
 bool  Greater(const std::pair<Class1, int>& p, Class1 iData)
 {
   return p.first > iData;
 }
template<class _Ty1,class _Ty2>
class CLessPair
{
public:
  bool operator()(const std::pair<_Ty1, _Ty2>& p1, const std::pair<_Ty1, _Ty2>& p2)const
  {
    return p1.first < p2.first;
  }
};
template<class _Ty1, class _Ty2>
class CGreatePair
{
public:
  bool operator()(const std::pair<_Ty1, _Ty2>& p1, const std::pair<_Ty1, _Ty2>& p2)const
  {
    return p1.first > p2.first;
  }
};

}

class CIndexVector

{

public:

template

CIndexVector(vector& data)

{

for (int i = 0; i < data.size(); i++)

{

m_indexs.emplace_back(i);

}

std::sort(m_indexs.begin(), m_indexs.end(), [data](const int& i1, const int& i2)

{

return data[i1] < data[i2];

});

}

int GetIndex(int index)

{

return m_indexs[index];

}

private:

vector m_indexs;

};

class CMedian

{

public:

void AddNum(int iNum)

{

m_queTopMin.emplace(iNum);

MakeNumValid();

MakeSmallBig();

}

void Remove(int iNum)

{

if (m_queTopMax.size() && (iNum <= m_queTopMax.top()))

{

m_setTopMaxDel.insert(iNum);

}

else

{

m_setTopMinDel.insert(iNum);

}

PopIsTopIsDel(m_queTopMin, m_setTopMinDel);
  PopIsTopIsDel(m_queTopMax, m_setTopMaxDel);
  MakeNumValid();
  MakeSmallBig();
}
double Median()
{
  const int iMaxNum = m_queTopMin.size() - m_setTopMinDel.size();
  const int iMinNum = m_queTopMax.size() - m_setTopMaxDel.size();
  if (iMaxNum > iMinNum)
  {
    return m_queTopMin.top();
  }
  return ((double)m_queTopMin.top() + m_queTopMax.top())/2.0;
}
template<class T>
void PopIsTopIsDel(T& que, std::unordered_multiset<int>& setTopMaxDel)
{
  while (que.size() && (setTopMaxDel.count(que.top())))
  {
    setTopMaxDel.erase(setTopMaxDel.find(que.top()));
    que.pop();
  }
}
void MakeNumValid()
{
  const int iMaxNum = m_queTopMin.size() - m_setTopMinDel.size();
  const int iMinNum = m_queTopMax.size() - m_setTopMaxDel.size();
  //确保两个队的数量
  if (iMaxNum > iMinNum + 1)
  {
    int tmp = m_queTopMin.top();
    m_queTopMin.pop();
    m_queTopMax.emplace(tmp);
    PopIsTopIsDel(m_queTopMin, m_setTopMinDel);
  }
  if (iMinNum > iMaxNum)
  {
    int tmp = m_queTopMax.top();
    m_queTopMax.pop();
    m_queTopMin.push(tmp);
    PopIsTopIsDel(m_queTopMax, m_setTopMaxDel);
  }
}
void MakeSmallBig()
{
  if (m_queTopMin.empty() || m_queTopMax.empty())
  {
    return;
  }
  while (m_queTopMin.top() < m_queTopMax.top())
  {
    const int iOldTopMin = m_queTopMin.top();
    const int iOldTopMax = m_queTopMax.top();
    m_queTopMin.pop();
    m_queTopMax.pop();
    m_queTopMin.emplace(iOldTopMax);
    m_queTopMax.emplace(iOldTopMin);
    PopIsTopIsDel(m_queTopMin, m_setTopMinDel);
    PopIsTopIsDel(m_queTopMax, m_setTopMaxDel);
  }
}
std::priority_queue<int> m_queTopMax;
std::priority_queue<int, vector<int>, greater<int>> m_queTopMin;
std::unordered_multiset<int> m_setTopMaxDel, m_setTopMinDel;

};

template

class CDistanceGrid

{

public:

CDistanceGrid(const vector<vector>& grid) :m_grid(grid), m_r(grid.size()), m_c(grid[0].size())

{

}
//单源路径 D 算法 ,时间复杂度:r*c*log(r*c)
inline int Dis(int r1, int c1, int r2, int c2)
{ 
  vector<vector<int>> vDis(iMaxRow, vector<int>(iMaxCol, INT_MAX));
  auto Add = [&vDis, this](std::priority_queue<pair<int, int>, vector<std::pair<int, int>>, greater<pair<int, int>>>& queCur, int iDis, int r, int c)
  {
    const int iRowColMask = iMaxCol * r + c;
    if (iDis >= vDis[r][c])
    {
      return;
    }
    queCur.emplace(iDis,iRowColMask);
    vDis[r][c] = iDis;
  };
  auto Move = [&](std::priority_queue<pair<int, int>, vector<std::pair<int, int>>, greater<pair<int, int>>>& queCur, int iDis, int r, int c)
  {
    if ((r < 0) || (r >= m_r))
    {
      return;
    }
    if ((c < 0) || (c >= m_c))
    {
      return;
    }
    if (m_grid[r][c] < 1)
    {
      return;
    }
    Add(queCur,iDis, r, c);
  };
  std::priority_queue<pair<int, int>, vector<std::pair<int, int>>, greater<pair<int, int>>> que;    
  Add(que,0,r1, c1);
  while (que.size())
  {
    const int iDis = que.top().first;
    const int iStart = que.top().second;
    que.pop();
    const int r = iStart / iMaxCol;
    const int c = iStart % iMaxCol;
    if ((r == r2) && (c == c2))
    {
      return iDis;
    }
    if (iDis > vDis[r][c])
    {
      continue;
    }
    
    Move(que, iDis + 1, r + 1, c);
    Move(que, iDis + 1, r - 1, c);
    Move(que, iDis + 1, r, c + 1);
    Move(que, iDis + 1, r, c - 1);
  }
  return -1;
}

private:

virtual bool IsCanMoveStatue(int r, int c)

{

return m_grid[r][c] >= 1;

}

const int m_r;

const int m_c;

const vector<vector>& m_grid;

};

class CBFSGridDist

{

public:

CBFSGridDist(const vector<vector>& bCanVisit, int r, int c) :m_bCanVisit(bCanVisit), m_r(m_bCanVisit.size()), m_c(m_bCanVisit[0].size())

{

m_vDis.assign(m_r, vector(m_c,INT_MAX/2));

Dist(r, c);

}

bool Vilid(const int r,const int c )

{

if ((r < 0) || (r >= m_r))

{

return false;

}

if ((c < 0) || (c >= m_c))

{

return false;

}

return true;

}

const vector<vector>& Dis()const

{

return m_vDis;

}

const vector<vector>& m_bCanVisit;

private:

//INT_MAX/2 表示无法到达

void Dist(int r, int c)

{

m_vDis.assign(m_r, vector(m_c, INT_MAX / 2));

vector<vector> vHasDo(m_r, vector(m_c));

std::queue<std::pair<int, int>> que;

auto Add = [&](const int& r, const int& c, const int& iDis)

{

if (!Vilid(r, c))

{

return;

}

if (vHasDo[r][c])

{

return;

}

if (!m_bCanVisit[r][c])

{

vHasDo[r][c] = true;

return;

}

if (iDis >= m_vDis[r][c])

{

return;

}

que.emplace(r, c);
    m_vDis[r][c] = iDis;
    vHasDo[r][c] = true;
  };
  Add(r, c, 0);
  while (que.size())
  {
    const int r = que.front().first;
    const int c = que.front().second;
    que.pop();
    const int iDis = m_vDis[r][c];
    Add(r + 1, c, iDis + 1);
    Add(r - 1, c, iDis + 1);
    Add(r, c + 1, iDis + 1);
    Add(r, c - 1, iDis + 1);
  }
}
vector<vector<int>> m_vDis;
const int m_r;
const int m_c;

};

class C2BNumTrieNode

{

public:

C2BNumTrieNode()

{

m_childs[0] = m_childs[1] = nullptr;

}

bool GetNot0Child(bool bFirstRight)

{

auto ptr = m_childs[bFirstRight];

if (ptr && (ptr->m_iNum >0))

{

return bFirstRight;

}

return !bFirstRight;

}

int m_iNum = 0;

C2BNumTrieNode* m_childs[2];

};

template

class C2BNumTrie

{

public:

C2BNumTrie()

{

m_pRoot = new C2BNumTrieNode();

}

void Add(int iNum)

{

m_setHas.emplace(iNum);

C2BNumTrieNode* p = m_pRoot;

for (int i = iLeveNum - 1; i >= 0; i–)

{

p->m_iNum++;

bool bRight = iNum & (1 << i);

if (nullptr == p->m_childs[bRight])

{

p->m_childs[bRight] = new C2BNumTrieNode();

}

p = p->m_childs[bRight];

}

p->m_iNum++;

}

void Del(int iNum)

{

auto it = m_setHas.find(iNum);

if (m_setHas.end() == it)

{

return;

}

m_setHas.erase(it);

C2BNumTrieNode* p = m_pRoot;

for (int i = iLeveNum - 1; i >= 0; i–)

{

p->m_iNum–;

bool bRight = iNum & (1 << i);

p = p->m_childs[bRight];

}

p->m_iNum–;

}

int MaxXor(int iNum)

{

C2BNumTrieNode* p = m_pRoot;

int iRet = 0;

for (int i = iLeveNum - 1; i >= 0; i–)

{

bool bRight = !(iNum & (1 << i));

bool bSel = p->GetNot0Child(bRight);

p = p->m_childs[bSel];

if (bSel == bRight)

{

iRet |= (1 << i);

}

}

return iRet;

}

C2BNumTrieNode* m_pRoot;

std::unordered_multiset m_setHas;

};

struct SValueItem

{

SValueItem()

{

}
SValueItem(int iValue)
{
  m_iCoefficient = iValue;
}
SValueItem operator*(const SValueItem& o)const
{
  SValueItem ret(m_iCoefficient*o.m_iCoefficient);
  int i = 0, j = 0;
  while ((i < m_vVars.size()) && (j < o.m_vVars.size()))
  {
    if (m_vVars[i] < o.m_vVars[j])
    {
      ret.m_vVars.emplace_back(m_vVars[i]);
      i++;
    }
    else
    {
      ret.m_vVars.emplace_back(o.m_vVars[j]);
      j++;
    }
  }
  ret.m_vVars.insert(ret.m_vVars.end(), m_vVars.begin()+i, m_vVars.end());
  ret.m_vVars.insert(ret.m_vVars.end(), o.m_vVars.begin()+j, o.m_vVars.end());
  return ret;
}
bool operator<(const SValueItem& o)const
{
  if (m_vVars.size() == o.m_vVars.size())
  {
    return m_vVars < o.m_vVars;
  }
  return m_vVars.size() > o.m_vVars.size();
}
vector<std::string> m_vVars;
int m_iCoefficient=1;//系数、倍率
std::string ToString()const
{
  std::ostringstream os;
  os << m_iCoefficient ;
  for (const auto&s : m_vVars)
  {
    os << "*" << s;
  }
  return os.str();
}

};

struct SValue

{

SValue()

{

}
SValue(int iValue)
{
  SValueItem item;
  item.m_iCoefficient = iValue;
  m_items.emplace(item);
}
SValue(std::string strName)
{
  SValueItem item;
  item.m_vVars.emplace_back(strName);
  m_items.emplace(item);
}
SValue operator-(const SValue& o)const
{
  SValue ret;
  ret.m_items = m_items;
  for (auto it : o.m_items)
  {
    ret -= it;
  }
  return ret;
}
SValue operator+(const SValue& o)const
{
  SValue ret;
  ret.m_items = m_items;
  for (auto it : o.m_items)
  {
    ret += it;
  }     
  return ret;
}
SValue operator*(const SValue& o)const
{
  SValue ret;
  for (const auto it : m_items)
  {
    for (const auto ij : o.m_items)
    {
      ret += it*ij;
    }
  }
  return ret;
}
SValue& operator+=(const SValueItem& item)
{
  auto it = m_items.find(item);
  if (m_items.end() == it)
  {
    m_items.emplace(item);
  }
  else
  {
    auto tmp = *it;
    tmp.m_iCoefficient += item.m_iCoefficient;
    m_items.erase(it);
    m_items.emplace(tmp);
  }
  return *this;
}
SValue& operator-=(const SValueItem& item)
{
  auto it = m_items.find(item);
  if (m_items.end() == it)
  {
    auto tmp = item;
    tmp.m_iCoefficient *= -1;
    m_items.emplace(tmp);
  }
  else
  {
    auto tmp = *it;
    tmp.m_iCoefficient -= item.m_iCoefficient;
    m_items.erase(it);
    m_items.emplace(tmp);
  }
  return *this;
}
vector<std::string> ToStrings()const
{
  vector<std::string> vRet;
  for (const auto& item : m_items)
  {
    if (0 == item.m_iCoefficient)
    {
      continue;
    }
    vRet.emplace_back(item.ToString());
  }
  return vRet;
}
std::set<SValueItem> m_items;

};

class CDelIndexs

{

public:

CDelIndexs()

{

}
CDelIndexs(int iSize)
{
  Init(iSize);
}
void Init(int iSize)
{
  m_bDels.assign(iSize, false);
  m_vNext.resize(iSize);
  for (int i = 0; i < iSize; i++)
  {
    m_vNext[i] = i + 1;
  }
}
void Del(int index)
{
  if ((index < 0) || (index >= m_vNext.size()))
  {
    return;
  }
  if (m_bDels[index])
  {
    return;
  }
  m_bDels[index] = true;
}
void SetCur(int index)
{
  if (index < 0)
  {
    m_iCur = m_vNext.size();
  }
  else
  {
    m_iCur = FreshCur(index);
  }
}
int NextIndex()
{
  if (m_iCur >= m_vNext.size())
  {
    return -1;
  }
  auto ret = m_iCur;
  SetCur(m_vNext[m_iCur]);
  return ret;
}

private:

int FreshCur(int index)

{

if (index >= m_vNext.size())

{

return m_vNext.size();

}

if (!m_bDels[index])

{

return index;

}

return m_vNext[index] = FreshCur(m_vNext[index]);
}
int m_iCur = 0;
vector<bool> m_bDels;
vector<int> m_vNext;

};

class CUnionFind

{

public:

CUnionFind(int iSize) :m_vConnetNO(iSize), m_vConnectSize(iSize, 1)

{

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

{

m_vConnetNO[i] = i;

}

m_iConnetSize = iSize;

}

int GetConnectNO(int iNode)

{

int& iConnectNO = m_vConnetNO[iNode];

if (iNode == iConnectNO)

{

return iNode;

}

return iConnectNO = GetConnectNO(iConnectNO);

}

void Union(int iNode1, int iNode2)

{

const int iConnectNO1 = GetConnectNO(iNode1);

const int iConnectNO2 = GetConnectNO(iNode2);

if (iConnectNO1 == iConnectNO2)

{

return ;

}

m_iConnetSize–;

if (iConnectNO1 > iConnectNO2)

{

UnionConnect(iConnectNO1, iConnectNO2);

}

else

{

UnionConnect(iConnectNO2, iConnectNO1);

}

}

int GetAConnectSizeByNode(int iNode)

{

return m_vConnectSize[GetConnectNO(iNode)];

}

bool IsConnect(int iNode1, int iNode2)

{

return GetConnectNO(iNode1) == GetConnectNO(iNode2);

}

int ConnetSize()const

{

return m_iConnetSize;

}

private:

void UnionConnect(int iFrom, int iTo)

{

m_vConnectSize[iTo] += m_vConnectSize[iFrom];

m_vConnetNO[iFrom] = iTo;

}

vector m_vConnetNO;//各点所在联通区域的编号,本联通区域任意一点的索引,为了增加可理解性,用最小索引

vector m_vConnectSize;//各联通区域点数量

int m_iConnetSize;

};

class CUnionFindMST

{

public:

CUnionFindMST(const int iNodeSize) :m_uf(iNodeSize)

{

}
void AddEdge(const int iNode1, const int iNode2, int iWeight)
{
  if (m_uf.IsConnect(iNode1, iNode2))
  {
    return;
  }
  m_iMST += iWeight;
  m_uf.Union(iNode1, iNode2);
}
void AddEdge(const vector<int>& v )
{
  AddEdge(v[0], v[1], v[2]);
}
int MST()
{
  if (m_uf.ConnetSize() > 1)
  {
    return -1;
  }
  return m_iMST;
}

private:

int m_iMST = 0;

CUnionFind m_uf;

};

class CNearestMST

{

public:

CNearestMST(const int iNodeSize) :m_bDo(iNodeSize), m_vDis(iNodeSize, INT_MAX), m_vNeiTable(iNodeSize)

{

}
void Init(const vector<vector<int>>& edges)
{
  for (const auto& v : edges)
  {
    Add(v);
  }
}
void Add(const vector<int>& v )
{
  m_vNeiTable[v[0]].emplace_back(v[1], v[2]);
  m_vNeiTable[v[1]].emplace_back(v[0], v[2]);
}
int MST(int start)
{
  int next = start;
  while ((next = AddNode(next)) >= 0);
  return m_iMST;
}
int MST(int iNode1, int iNode2,int iWeight)
{
  m_bDo[iNode1] = true;
  for (const auto& it : m_vNeiTable[iNode1])
  {
    if (m_bDo[it.first])
    {
      continue;
    }
    m_vDis[it.first] = min(m_vDis[it.first],(long long) it.second);
  }
  m_iMST = iWeight;
  int next = iNode2;
  while ((next = AddNode(next)) >= 0);
  return m_iMST;
}

private:

int AddNode(int iCur)

{

m_bDo[iCur] = true;

for (const auto& it : m_vNeiTable[iCur])

{

if (m_bDo[it.first])

{

continue;

}

m_vDis[it.first] = min(m_vDis[it.first], (long long)it.second);

}

int iMinIndex = -1;
  for (int i = 0; i < m_vDis.size(); i++)
  {
    if (m_bDo[i])
    {
      continue;
    }
    if ((-1 == iMinIndex) || (m_vDis[i] < m_vDis[iMinIndex]))
    {
      iMinIndex =i;   
    }
  }
  if ( -1 != iMinIndex)
  {
    if (INT_MAX == m_vDis[iMinIndex])
    {
      m_iMST = -1;
      return -1;
    }
    m_iMST += m_vDis[iMinIndex];
  }
  
  return iMinIndex;
}
vector<bool> m_bDo;
vector<long long> m_vDis;
vector < vector<std::pair<int, int>>> m_vNeiTable;
long long m_iMST = 0;

};

typedef pair<long long,int> PAIRLLI;

class CDis

{

public:

static void Dis(vector& vDis, int start, const vector<vector<pair<int, int>>>& vNeiB)

{

std::priority_queue<PAIRLLI, vector, greater> minHeap;

minHeap.emplace(0, start);

while (minHeap.size())

{

const long long llDist = minHeap.top().first;

const int iCur = minHeap.top().second;

minHeap.pop();

if (-1 != vDis[iCur])

{

continue;

}

vDis[iCur] = llDist;

for (const auto& it : vNeiB[iCur])

{

minHeap.emplace(llDist + it.second, it.first);

}

}

}

};

class CNearestDis

{

public:

CNearestDis(int iSize) :m_iSize(iSize), DIS(m_vDis), PRE(m_vPre)

{

}
void Cal(int start, const vector<vector<pair<int, int>>>& vNeiB)
{
  m_vDis.assign(m_iSize, -1);
  m_vPre.assign(m_iSize, -1);
  vector<bool> vDo(m_iSize);//点是否已处理
  auto AddNode = [&](int iNode)
  {
    //const int iPreNode = m_vPre[iNode];
    long long llPreDis = m_vDis[iNode];
    vDo[iNode] = true;
    for (const auto& it : vNeiB[iNode])
    {
      if (vDo[it.first])
      {
        continue;
      }
      if ((-1 == m_vDis[it.first]) || (it.second + llPreDis < m_vDis[it.first]))
      {
        m_vDis[it.first] = it.second + llPreDis;
        m_vPre[it.first] = iNode;
      }       
    }
    long long llMinDis = LLONG_MAX;
    int iMinIndex = -1;
    for (int i = 0; i < m_vDis.size(); i++)
    {
      if (vDo[i])
      {
        continue;
      }
      if (-1 == m_vDis[i])
      {
        continue;
      }
      if (m_vDis[i] < llMinDis)
      {
        iMinIndex = i;
        llMinDis = m_vDis[i];
      }
    }
    return (LLONG_MAX == llMinDis) ? -1 : iMinIndex;
  };
  int next = start;
  m_vDis[start] = 0;
  while (-1 != (next= AddNode(next)));
}
void Cal(const int start, vector<vector<int>>& edges)
{
  vector<vector<pair<int, int>>> vNeiB(m_iSize);
  for (int i = 0; i < edges.size(); i++)
  {
    const auto& v = edges[i];
    vNeiB[v[0]].emplace_back(v[1], v[2]);
    vNeiB[v[1]].emplace_back(v[0], v[2]);
  }
  Cal(start, vNeiB);
}
const vector<long long>& DIS;
const vector<int>& PRE;

private:

const int m_iSize;

vector m_vDis;//各点到起点的最短距离

vector m_vPre;//最短路径的前一点

};

class CNeiBo2

{

public:

CNeiBo2(int n, vector<vector>& edges, bool bDirect)

{

m_vNeiB.resize(n);

for (const auto& v : edges)

{

m_vNeiB[v[0]].emplace_back(v[1]);

if (!bDirect)

{

m_vNeiB[v[1]].emplace_back(v[0]);

}

}

}

vector<vector> m_vNeiB;

};

struct SDecimal

{

SDecimal(int iNum=0, int iDeno = 1)

{

m_iNum = iNum;

m_iDeno = iDeno;

int iGCD = GCD(abs(m_iNum), abs(m_iDeno));

m_iNum /= iGCD;

m_iDeno /= iGCD;

if (m_iDeno < 0)

{

m_iDeno = -m_iDeno;

m_iNum = -m_iNum;

}

}

SDecimal operator*(const SDecimal& o)const

{

return SDecimal(m_iNumo.m_iNum, m_iDenoo.m_iDeno);

}

SDecimal operator/(const SDecimal& o)const

{

return SDecimal(m_iNumo.m_iDeno, m_iDenoo.m_iNum);

}

SDecimal operator+(const SDecimal& o)const

{

const int iGCD = GCD(m_iDeno, o.m_iDeno);

const int iDeno = m_iDenoo.m_iDeno / iGCD;
return SDecimal(m_iNum
(iDeno / m_iDeno) + o.m_iNum*(iDeno / o.m_iDeno), iDeno);

}

SDecimal operator-(const SDecimal& o)const

{

const int iGCD = GCD(m_iDeno, o.m_iDeno);

const int iDeno = m_iDenoo.m_iDeno / iGCD;
return SDecimal(m_iNum
(iDeno / m_iDeno) - o.m_iNum*(iDeno / o.m_iDeno), iDeno);

}

bool operator==(const SDecimal& o)const

{

return (m_iNum == o.m_iNum) && (m_iDeno == o.m_iDeno);

}

bool operator<(const SDecimal& o)const

{

auto tmp = *this - o;

return tmp.m_iNum < 0;

}

int m_iNum=0;//分子

int m_iDeno=1;//分母

};

struct point{

double x, y;

point(double i, double j) :x(i), y(j){}

};

//算两点距离

double dist(double x1, double y1, double x2, double y2){

return sqrt((x1 - x2)(x1 - x2) + (y1 - y2)(y1 - y2));

}

//计算圆心

point CircleCenter(point& a, point& b, int r){

//算中点

point mid((a.x + b.x) / 2.0, (a.y + b.y) / 2.0);

//AB距离的一半

double d = dist(a.x, a.y, mid.x, mid.y);

//计算h

double h = sqrt(rr - dd);

//计算垂线

point ba(b.x - a.x, b.y - a.y);

point hd(-ba.y, ba.x);

double len = sqrt(hd.xhd.x + hd.yhd.y);

hd.x /= len, hd.y /= len;

hd.x *= h, hd.y *= h;

return point(hd.x + mid.x, hd.y + mid.y);

}

class C01LineTree

{

public:

C01LineTree(const vector& nums) :m_iEleSize(nums.size())

{

m_arr.resize(m_iEleSize * 4);

Init(nums,1, 1, m_iEleSize);

m_vNeedFreshChilds.assign(m_iEleSize * 4, false);

}

void Rotato(int iLeftZeroIndex,int iRightZeroIndex )

{

int iRotatoLeft = iLeftZeroIndex + 1;

int iRotatoRight = iRightZeroIndex + 1;

Rotato(1, 1, m_iEleSize, iRotatoLeft, iRotatoRight);

}

int Query()

{

return m_arr[1];

}

private:

void Rotato(int iSaveIndex, int iDataBegin, int iDataEnd, int iRotatoLeft, int iRotatoRight)

{

if ((iRotatoLeft <= iDataBegin) && (iRotatoRight >= iDataEnd))

{//整个范围需要更新

RotatoSelf(iSaveIndex, iDataBegin, iDataEnd);

return;

}

int iMid = iDataBegin + (iDataEnd - iDataBegin) / 2;
  if (m_vNeedFreshChilds[iSaveIndex])
  {
    RotatoSelf(iSaveIndex * 2, iDataBegin, iMid);
    RotatoSelf(iSaveIndex * 2 + 1, iMid + 1, iDataEnd);
    m_vNeedFreshChilds[iSaveIndex] = false;
  } 
  if (iMid >= iRotatoLeft)
  {
    Rotato(iSaveIndex * 2, iDataBegin, iMid, iRotatoLeft, iRotatoRight);
  }
  if (iMid + 1 <= iRotatoRight)
  {
    Rotato(iSaveIndex * 2 + 1, iMid + 1, iDataEnd, iRotatoLeft, iRotatoRight);
  }
  m_arr[iSaveIndex] = m_arr[iSaveIndex * 2] + m_arr[iSaveIndex * 2 + 1];
}
void RotatoSelf(int iSaveIndex, int iDataBegin, int iDataEnd)
{
  //总数量 - 翻转后0(翻转前1)的数量
  m_arr[iSaveIndex] = (iDataEnd - iDataBegin + 1) - m_arr[iSaveIndex];
  //懒惰法,标记本节点的子孙节点没更新
  m_vNeedFreshChilds[iSaveIndex] = !m_vNeedFreshChilds[iSaveIndex];
}
void Init(const vector<int>& nums, int iSaveIndex,int iDataBegin, int iDataEnd)
{
  if (iDataBegin == iDataEnd)
  {
    m_arr[iSaveIndex] = nums[iDataBegin - 1];
    return;
  }
  int iMid = iDataBegin + (iDataEnd - iDataBegin) / 2;
  Init(nums, iSaveIndex * 2  , iDataBegin, iMid);
  Init(nums, iSaveIndex * 2 + 1, iMid + 1, iDataEnd);
  m_arr[iSaveIndex] = m_arr[iSaveIndex * 2] + m_arr[iSaveIndex * 2 + 1];
}
const int m_iEleSize;
vector<int> m_arr;
vector<bool> m_vNeedFreshChilds;

};

/*

struct TreeNode {

int val;

TreeNode *left;

TreeNode *right;

TreeNode(int x) : val(x), left(NULL), right(NULL) {}

TreeNode(int x, int iLeft) : val(x), left(new TreeNode(iLeft)), right(nullptr) {}

TreeNode(int x, int iLeft, int iRghit) : val(x), left(new TreeNode(iLeft)), right(new TreeNode(iRghit)) {}

};

namespace NTree

{

TreeNode* Init(const vector& nums, int iNull = 10000)

{

if (0 == nums.size())

{

return nullptr;

}

vector<TreeNode*> ptrs(nums.size() + 1), ptrParent(1);

for (int i = 0; i < nums.size(); i++)

{

if (iNull == nums[i])

{

continue;

}

const int iNO = i + 1;

ptrs[iNO] = new TreeNode(nums[i]);

ptrParent.emplace_back(ptrs[iNO]);

if (1 == iNO)

{

continue;

}

if (iNO & 1)

{//奇数是右支

ptrParent[iNO / 2]->right = ptrs[iNO];

}

else

{

ptrParent[iNO / 2]->left = ptrs[iNO];

}

}

return ptrs[1];

}

}

*/

class Solution {

public:

int kInversePairs(int n, int k) {

//n为1时,只有一种情况:逆序0

vector<C1097Int<>> pre = { C1097Int<>(1) };

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

{

const int iNewLen = min(k + 1, (int)pre.size() + i);

vector<C1097Int<>> dp(iNewLen);

C1097Int<> iSum = 0;

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

{

if (j < pre.size())

{

iSum += pre[j];

}

const int iDelIndex = j - i;

if (iDelIndex >= 0)

{

iSum -= pre[iDelIndex];

}

dp[j] = iSum;

}

pre.swap(dp);

}

return (k < pre.size()) ? pre[k].ToInt() : 0;

}

};


相关文章
|
2天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
17 5
|
2天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
15 2
|
10天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
16天前
|
算法
|
8天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
15天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
35 4
|
2月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
69 2
|
3月前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
131 2
动态规划算法学习三:0-1背包问题
|
3月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
58 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
3月前
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
87 0
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)