ACM模板

      之前做过acm,总结出来了一些算法模板。这些是我在搞懂先自己写然后想大牛靠拢不断优化的结果,可能有些是大牛们的源代码,在此一并发出,希望对大家有所帮助,代码中可能有错,在此表示歉意。

[cpp]  view plain  copy
  1.  动态规划模板  
  2. 处理求矩阵的最大子矩  
  3. //************************************************************  
  4. //求a[n][m]的最大子矩阵  
  5. ///计算从某固定行开始起连续列b[i,j]动态规划求最大值  
  6. int dp( const int *b,int m)  
  7. {  
  8.     int sum ,max,i;  
  9.     sum=max=b[0];  
  10.     for(i=1;i
  11.     {  
  12.         if(sum>0)sum+=b[i];  
  13.         else sum=b[i];  
  14.         if(sum>max)max=sum;  
  15.     }  
  16.     return max;  
  17. }  
  18.   
  19. //b[k]可以取到任意连续行的排列组合  
  20. max=-999999999;   
  21. for(i=0;i//控制具体哪一行开始  
  22. {  
  23.     memset(b,0,sizeof(b));  
  24.     for(j=i;j//表示从第i行到最后n行中间每列累加得b[k]  
  25.     {  
  26.         for(k=0;k
  27.             b[k]+=a[j][k];  
  28.         if(dp(b,m)>max) max=dp(b,m);  
  29.     }  
  30. }  
  31. //************************************************************  
  32.   
  33. 动态规划求最大面积  
  34. //************************************************************  
  35.  {  
  36.   首先开辟数组a[N],l[N],r[N]  
  37. ////找出其左右区间比其大的区间长度  
  38.         l[1]=1;    
  39.         r[n]=n;    
  40.        for (i=2; i<=n; ++i)    
  41.         {    
  42.            t=i;    
  43.             while (t>1 && a[i]<=a[t-1]) t=l[t-1];    
  44.             l[i]=t;    
  45.         }    
  46.         for (i=n-1; i>=1; --i)    
  47.        {    
  48.             t=i;    
  49.             while (t
  50.             r[i]=t;    
  51.         }   
  52.         /////分别以每个小矩形的高度为高求大矩形面积,并找出其最大者  
  53.         max=0;    
  54.         for (i=1; i<=n; ++i)    
  55.         {    
  56.             if ((r[i]-l[i]+1)*a[i]>max) max=(r[i]-l[i]+1)*a[i];    
  57.        }   
  58. }  
  59. //************************************************************  
  60.   
  61. 最长公共子序列  
  62. //*********************************************************  
  63. //算法1:时间复杂度为O(N*M),空间复杂度为O(N*N)  
  64. const int MAXN=1000;  
  65. char str1[MAXN],str2[MAXN];  
  66. int dp[MAXN][MAXN];  
  67.   
  68. int LCS1(char *str1,char *str2)  
  69. {  
  70.     int len1=strlen(str1);  
  71.     int len2=strlen(str2);  
  72.     int i,j;  
  73.     memset(dp,0,sizeof(dp));  
  74.     for(i=1;i<=len1;i++)  
  75.     {  
  76.         for(j=1;j<=len2;j++)  
  77.         {  
  78.             if(str1[i-1]==str2[j-1])  
  79.                 dp[i][j]=dp[i-1][j-1]+1;  
  80.             else if(dp[i-1][j]>dp[i][j-1])  
  81.                 dp[i][j]=dp[i-1][j];  
  82.             else dp[i][j]=dp[i][j-1];  
  83.         }  
  84.     }  
  85.     return dp[len1][len2];  
  86. }  
  87.   
  88. //===============================================//算法2:时间复杂度为O(N*M),空间复杂度为O(N)  
  89. const int MAXN=1000;  
  90. char str1[MAXN],str2[MAXN];  
  91. int dp[2][MAXN];//采用滚动数组优化  
  92.   
  93. int LCS2(char *str1,char *str2)  
  94. {  
  95.     int len1=strlen(str1);  
  96.     int len2=strlen(str2);  
  97.     int i,j,k;  
  98.     memset(dp,0,sizeof(dp));  
  99.     for(i=1;i<=len1;i++)  
  100.     {  
  101.         k=i&1;  
  102.         for(j=1;j<=len2;j++)  
  103.         {  
  104.             if(str1[i-1]==str2[j-1])  
  105.                 dp[k][j]=dp[k][j-1]+1;  
  106.             else if(dp[k^1][j]>dp[k][j-1])  
  107.                 dp[k][j]=dp[k^1][j];  
  108.             else dp[k][j]=dp[k][j-1];  
  109.         }  
  110.     }  
  111.     return dp[k][len2];  
  112. }  
  113. //*********************************************************  
  114.   
  115. 最长公共递增子序列  
  116. //************************************************************  
  117.  //其中a[n],b[n]分别存放俩序列  
  118.     memset(dp,0,sizeof(dp));  
  119.     max=0;  
  120.     for(i=0;i
  121.     {  
  122.         k=0;  
  123.         for(j=0;j
  124.         {  
  125.             //////////////保证递增又保证找到最大  
  126.             if(a[i]>b[j]&&dp[k]
  127.                 k=j;      
  128.             if(a[i]==b[j])  
  129.                 dp[j]=dp[k]+1;  
  130.             if(max
  131.                 max=dp[j];  
  132.         }  
  133.     }  
  134. //************************************************************  
  135.   
  136.   
  137. 数塔问题  
  138. //************************************************************  
  139. //n,m分别表示行数列数  
  140. void shuta(int n,int m)  
  141. {  
  142.     int i,j;  
  143.     memset(data,0,sizeof(data));  
  144.     memset(dp,0,sizeof(dp));      
  145.     for(i=1;i<=n;i++)  
  146.     {  
  147.         for(j=1;j<=i;j++)  
  148.         {  
  149.             cin>>data[i][j];  
  150.         }  
  151.     }  
  152.     for(j=1;j<=m;j++)  
  153.         dp[n][j]=data[n][j];  
  154.     for(i=n-1;i>=1;i--)  
  155.     {  
  156.         for(j=i;j>=1;j--)  
  157.         {  
  158.             dp[i][j]=max(dp[i+1][j]+data[i][j],dp[i+1][j+1]+data[i][j]);  
  159.         }     
  160.     }  
  161. }  
  162. //************************************************************  
  163.   
  164. 最长递增子序列  
  165. //求严格递增子序列的最长长度  
  166. //************************************************************  
  167. //算法1的时间复杂度为O(N*log(N))  
  168. const int MAXN=1000;  
  169. int data[MAXN];//存放原始数据  
  170. int MaxV[MAXN];//MaxV[i]存放长度为i的严格递增子序列的最大值的最小值  
  171.   
  172. //二分查找返回MaxV中大于等于x的组靠左的下标  
  173. int BinaryResearch(int x,int len)  
  174. {  
  175.     int mid,low=1,high=len;  
  176.     while(low<=high)  
  177.     {  
  178.         mid=(low+high)>>1;  
  179.         if(MaxV[mid]
  180.             low=mid+1;  
  181.         else high=mid-1;  
  182.     }  
  183.     return low;  
  184. }  
  185. //返回原序列中严格递增子序列的最长长度  
  186. int LIS2(int n)  
  187. {  
  188.     int i,len=1;  
  189.     MaxV[1]=data[0];  
  190.     for(i=1;i
  191.     {  
  192.         if(data[i]>MaxV[len])//比长度为len的子序列最大值大,直接加进末尾  
  193.             MaxV[++len]=data[i];  
  194.         else   
  195.         {  
  196.             int pos=BinaryResearch(data[i],len);  
  197.             MaxV[pos]=data[i];  
  198.         }  
  199.     }  
  200.     return len;  
  201. }  
  202. //===============================================  
  203. //算法2的时间复杂度为O(N*N)  
  204. int dp[MAXN];  
  205. //返回原序列中严格递增子序列的最长长度  
  206. int LIS1(int n)  
  207. {  
  208.     int i,j,lmax;  
  209.     lmax=0;  
  210.     for(i=0;i
  211.     {  
  212.         dp[i]=1;  
  213.         for(j=0;j
  214.         {  
  215.             if(data[i]>data[j]&&dp[j]+1>dp[i])  
  216.                 dp[i]=dp[j]+1;  
  217.         }  
  218.         if(dp[i]>lmax)lmax=dp[i];  
  219.     }  
  220.     return lmax;  
  221. }  
  222. //************************************************************  
  223.   
  224. 最大字段和  
  225. //************************************************************  
  226. void MSS(int n)  
  227. {  
  228.     int i;  
  229.     int max=NINF;  
  230.     memset(dp,0,sizeof(dp));  
  231.     for(i=1;i<=n;i++)  
  232.     {  
  233.         if(dp[i-1]<=0)  
  234.             dp[i]=data[i];  
  235.         else dp[i]=dp[i-1]+data[i];  
  236.         if(max
  237.             max=dp[i];  
  238.     }  
  239.     cout<
  240. }  
  241. //************************************************************  
  242.   
  243. 多重背包  
  244. //************************************************************  
  245. int dp[100000+10];//视具体情况而定  
  246. struct node  
  247. {  
  248.     int num,weight,value;//分别代表每种物品的数量、重量、价值  
  249. }Good[15];//定义每个物品的结构体  
  250. int Max_weight;//背包的载重量  
  251. int max(int a,int b)  
  252. {  
  253.     return a
  254. }  
  255. void ZeroOnePack(int weight,int value,int lim)  
  256. //对应01背包的求法  
  257. {  
  258.     for(int i=lim;i>=weight;i--)  
  259.         dp[i]=max(dp[i],dp[i-weight]+value);  
  260. }  
  261. void CompletePack(int weight,int value,int lim)  
  262. //对应完全背包的求法  
  263. {  
  264.     for(int i=weight;i<=lim;i++)  
  265.         dp[i]=max(dp[i],dp[i-weight]+value);  
  266. }  
  267. void MultiplePack(int weight,int value,int amount,int lim)  
  268. //选定物品后的多重背包的求法  
  269. {  
  270.     if(weight*amount>=lim)CompletePack(weight,value,lim);  
  271.     else  
  272.     {  
  273.         for(int k=1;k
  274.         {  
  275.             ZeroOnePack(k*weight,k*value,lim);  
  276.             amount-=k;  
  277.             k<<=1;  
  278.         }  
  279.         ZeroOnePack(amount*weight,amount*value,lim);  
  280.     }  
  281. }  
  282. void Solve(int n)  
  283. //解决物品种类数为n的多重背包问题求法  
  284. {  
  285.     memset(dp,0,sizeof(dp));  
  286.     for(int i=1;i<=n;i++)  
  287.         MultiplePack(Good[i].weight,Good[i].value,Good[i].num,Max_weight);  
  288. }  
  289. //************************************************************  
  290.   
  291.   
  292.   
  293.   
  294.   
  295. 数据结构          
  296. 单调队列  
  297. const int MAXN=100000+10;  
  298. int da[MAXN],Inc[MAXN],Dec[MAXN];  
  299. int n,m,k,front1,rear1,front2,rear2;  
  300. //维护双端单调队列,求da[]中满足m<=Max-Min<=k最长连续子序列  
  301. int Queue()  
  302. {  
  303.     front1=0,rear1=-1,front2=0,rear2=-1;  
  304.     int i,ans=0,start=0;  
  305.     for(i=0;i
  306.     {  
  307.         while(front1<=rear1&&da[Dec[rear1]]<=da[i])//保证Dec队列在start-i区间内的递减  
  308.             rear1--;  
  309.         Dec[++rear1]=i;  
  310.         while(front2<=rear2&&da[Inc[rear2]]>=da[i])//保证inc队列在start-i区间内的递增  
  311.             rear2--;  
  312.         Inc[++rear2]=i;  
  313.         while(da[Dec[front1]]-da[Inc[front2]]>k)  
  314.         {  
  315.             //保证区间左端点向后滑动一个长度  
  316.             if(Dec[front1]-Inc[front2]<0)  
  317.             {  
  318.                 start=Dec[front1]+1;  
  319.                 front1++;  
  320.             }  
  321.             else  
  322.             {  
  323.                 start=Inc[front2]+1;  
  324.                 front2++;  
  325.             }  
  326.         }  
  327.         //满足m<=Max-Min<=k  
  328.         if(da[Dec[front1]]-da[Inc[front2]]>=m)  
  329.         {  
  330.             if(i-start+1>ans)  
  331.                 ans=i-start+1;  
  332.         }  
  333.     }  
  334.     return ans;  
  335. }  
  336.   
  337. 并查集  
  338. //*****************************************************************  
  339. 1.求父亲节点并压缩路径  
  340. int par[MAX];  
  341. int Get_par(int a)  
  342. //查找a的父亲节点并压缩路径  
  343. {  
  344.     if(par[a]==a)  
  345.         return par[a];  
  346.     //注意语句的顺序  
  347.     int pa=par[a];  
  348.     par[a]=Get_par(par[a]);  
  349. //  
  350.     return par[a];  
  351. }  
  352.   
  353. 2.合并  
  354. void Merge(int a,int b)  
  355. //合并a,b  
  356. {  
  357.     int pa,pb;  
  358.     pa=Get_par(a);  
  359.     pb=Get_par(b);  
  360.     par[pa]=pb;  
  361. }  
  362. //*****************************************************************  
  363.   
  364. 线段树  
  365. 不带延迟更新的操作  
  366. //************************************************************  
  367. int da[MAXN];  
  368. struct node   
  369. {  
  370.     int left,right,sum;//sum此处灵活处理  
  371. }tree[MAXN*4];  
  372. //1.建立以left,right为左右边界,将数组da中元素存储在首地址从1开始的线段树tree的叶节点上  
  373. void Build( int id,int left,int right)  
  374. {  
  375.     tree[id].left=left;  
  376.     tree[id].right=right;  
  377.     if(left==right)  
  378.     {  
  379.         //tree[id].sum=da[left];//此处可以直接初始化为对应da[left]  
  380.         return ;  
  381.     }  
  382.     else  
  383.     {  
  384.         int mid =(left+right)>>1;          
  385.         Build(id<<1,left,mid);  
  386.         Build((id<<1)|1,mid+1,right);  
  387.         //tree[id].sum=tree[(id<<1)].sum+tree[(id<<1)|1].sum;  
  388.    }  
  389. }  
  390.   
  391. //2.在线段树的叶节点pos处加val  
  392. void Updata(int id,int pos,int val)  
  393. {  
  394.     tree[id].sum+=val;  
  395.     if(tree[id].left==tree[id].right&&tree[id].left==pos)  
  396.     {  
  397.         return ;  
  398.     }  
  399.     int mid=(tree[id].left+tree[id].right)>>1;  
  400.     if(pos<=mid)   
  401.         Updata(id<<1,pos,val);  
  402.     else   
  403.         Updata((id<<1)|1,pos,val);  
  404. }  
  405.   
  406. //3.查询区间[left,right]上的和  
  407. int Query(int id,int left,int right)  
  408. {  
  409.     if(tree[id].left==left&&tree[id].right==right)  
  410.     {  
  411.         return tree[id].sum;  
  412.     }  
  413.     int mid=(tree[id].left+tree[id].right)>>1;  
  414.     if(right<=mid)  
  415.         return Query(id<<1,left,right);  
  416.     if(left>=mid+1)  
  417.         return Query((id<<1)|1,left,right);  
  418.     return Query(id<<1,left,mid)+Query((id<<1)|1,mid+1,right);  
  419. }  
  420. //************************************************************  
  421.   
  422. 线段树的延迟更新  
  423. //*****************************************************  
  424. const int MAXN=100000+100;  
  425. struct node   
  426. {  
  427.     int left,right,add;  
  428.     int Max;  
  429. }tree[MAXN*4];  
  430.   
  431. void build(int id, int left, int right)  
  432. {  
  433.     tree[id].add=0;  
  434.     tree[id].left=left;  
  435.     tree[id].right=right;  
  436.     tree[id].Max=0;  
  437.     if(left==right)  
  438.     {  
  439.         return ;  
  440.     }  
  441.     else  
  442.     {  
  443.         int mid=(left+right)>>1;          
  444.         build(id<<1,left,mid);  
  445.         build((id<<1)|1,mid+1,right);  
  446.     }  
  447. }  
  448.   
  449. void updata(int id,int left,int right,int adi)  
  450. {  
  451.     if(tree[id].left==left&&tree[id].right==right)  
  452.     {  
  453.         tree[id].add+=adi;  
  454.         return ;  
  455.     }  
  456.     int mid=(tree[id].left+tree[id].right)>>1;  
  457.     if(right<=mid)  
  458.         updata(id<<1,left,right,adi);  
  459.     else if(left>mid)  
  460.         updata((id<<1)|1,left,right,adi);  
  461.     else  
  462.     {  
  463.         updata(id<<1,left,mid,adi);  
  464.         updata((id<<1)|1,mid+1,right,adi);  
  465.     }  
  466.     tree[id].Max=max(tree[id<<1].Max+tree[id<<1].add,tree[(id<<1)|1].Max+tree[(id<<1)|1].add);  
  467. }  
  468.   
  469. int query(int id,int left,int right)  
  470. {  
  471.     if(tree[id].left==left&&tree[id].right==right)  
  472.     {  
  473.         return tree[id].Max+tree[id].add;  
  474.     }  
  475.     int mid=(tree[id].left+tree[id].right)>>1;  
  476.     if(tree[id].add!=0)  
  477.     {  
  478.         updata(id<<1,tree[id].left,mid,tree[id].add);  
  479.         updata((id<<1)|1,mid+1,tree[id].right,tree[id].add);  
  480.         tree[id].Max=max(tree[id<<1].Max+tree[id<<1].add,tree[(id<<1)|1].Max+tree[(id<<1)|1].add);  
  481.         tree[id].add=0;  
  482.     }  
  483.     if(right<=mid)  
  484.         return query(id<<1,left,right);  
  485.     else if(left>mid )  
  486.         return query((id<<1)|1,left,right);  
  487.     else   
  488.     {  
  489.         return max(query(id<<1,left,mid),query((id<<1)|1,mid+1,right));  
  490.     }  
  491. }  
  492. //*****************************************************************  
  493.   
  494. RMQ问题的ST算法  
  495. //*****************************************************************  
  496. const int MAXN=50000+100;  
  497. const int Mpow=16;//保证2^(Mpow)>MAXN即可  
  498. int data[MAXN];  
  499. int Maxdp[MAXN][Mpow];  
  500. int Mindp[MAXN][Mpow];  
  501. inline int Min(int a,int b)  
  502. {  
  503.     return a
  504. }  
  505. inline int Max(int a,int b)  
  506. {  
  507.     return a>b?a:b;  
  508. }  
  509. inline void init(int n)  
  510. {  
  511.     for(int i=1;i<=n;i++)  
  512.     {  
  513.         Mindp[i][0]=Maxdp[i][0]=data[i];  
  514.     }  
  515. }  
  516. //预处理过程,时间复杂度为O(N*log(N))  
  517. //ST算法求区间最值  
  518. //dp[i][j]表示区间[i,i+2^j-1]最值  
  519. //求dp[i][j]时将其分成dp[i][j-1],dp[i+2^(j-1)][j-1]  
  520. //[i,i+2^j-1]=[i,i+2^(j-1)-1]+[i+2^(j-1),i+2^(j-1)+2^(j-1)-1]  
  521. inline void Rmp_ST(int n)  
  522. {  
  523.     int l,s;  
  524.     for(l=1;l<=16;l++)  
  525.     {  
  526.         for(s=1;s<=n;s++)  
  527.         {  
  528.             if(s+(1<
  529.             {  
  530.                 Maxdp[s][l]=Max(Maxdp[s][l-1],Maxdp[s+(1<<(l-1))][l-1]);  
  531.                 Mindp[s][l]=Min(Mindp[s][l-1],Mindp[s+(1<<(l-1))][l-1]);  
  532.             }  
  533.         }  
  534.     }  
  535. }  
  536. //查询[s,e]区间最值,下标从1-n  
  537. //求一个最大的k,是k满足2^k<=e-s+1  
  538. //原理:区间[s,e]=区间[s,s+2^k-1]+区间[e-2^k+1,e]  
  539. //s<=e-2^k+1,s+2^k-1<=e保证刚好完全覆盖  
  540. inline void query()  
  541. {  
  542.     int s,e,Min_ans,Max_ans;  
  543.     scanf("%d%d",&s,&e);  
  544.     int k=(int)(log(1.0*e-s+1)/log(2.0));  
  545.     Min_ans=Min(Mindp[s][k],Mindp[e-(1<<(k))+1][k]);  
  546.     Max_ans=Max(Maxdp[s][k],Maxdp[e-(1<<(k))+1][k]);  
  547.     printf("%d\n",Max_ans-Min_ans);  
  548. }  
  549. //*****************************************************************  
  550.   
  551. 一维树状数组  
  552. //************************************************************  
  553. const int MAXN=8000+100;  
  554. int C[MAXN];  
  555. int Lowbit[MAXN];  
  556. //C[i] = a[i-lowbit(i)+1] + …+ a[i],下表从1开始  
  557. //Lowbit[i]=i&(i^(i-1));或Lowbit[i]=i&(-i);   
  558. //1.查询  
  559. int QuerySum(int p)  
  560. //查询原数组中下标1-p的元素的和   
  561. {   
  562.    int nSum=0;   
  563.    while(p>0)   
  564.    {    
  565.       nSum+=C[p];   
  566.       p-=Lowbit[p];   
  567.    }   
  568.     return nSum;   
  569. }   
  570.   
  571. //2.修改+初始化  
  572. void Modify(int p,int val)   
  573. //原数组中下表为p的元素+val,导致C[]数组中部分元素值的改变  
  574. {   
  575.     while(p<=MAXN-10)   
  576.    {   
  577.       C[p]+=val;   
  578.       p+=Lowbit[p];   
  579.     }   
  580. }   
  581. //************************************************************  
  582.   
  583. 二维树状数组  
  584. //*****************************************************************  
  585. 1.修改  
  586. void Add( int y, int x,int a)  
  587. //原数组中下表为[y][x]的元素+a,导致C[][]数组中部分元素值的改变  
  588. {  
  589.     while( y <= s )  
  590.     {   
  591.         int tmpx = x;  
  592.         while( tmpx <= s )  
  593.         {  
  594.             C[y][tmpx] += a;  
  595.             tmpx += Lowbit[tmpx];  
  596.         }  
  597.         y += Lowbit[y];  
  598.     }  
  599. }  
  600. 2.查询  
  601. int QuerySum( int y, int x)  
  602. //查询第1行到第y行,第1列到第x列的和  
  603. {  
  604.     int nSum = 0;  
  605.     while( y > 0 )   
  606.     {  
  607.         int tmpx = x;  
  608.         while( tmpx > 0)   
  609.         {  
  610.             nSum += C[y][tmpx];  
  611.             tmpx -= Lowbit[tmpx];  
  612.         }  
  613.         y -= Lowbit[y];  
  614.     }  
  615.     return nSum;  
  616. }  
  617. //*****************************************************************  
  618.   
  619. 划分树  
  620. //*****************************************************************  
  621. const int MAXN=100010;  
  622. int tree[30][MAXN];//表示每层每个位置的值  
  623. int sorted[MAXN];//已经排序的数  
  624. int toleft[30][MAXN];//toleft[p][i]表示第p层从1到i有多少个数分入左边  
  625.   
  626. //创建划分树  
  627. //时间复杂度为O(N*log(N))  
  628. void build(int l,int r,int dep)  
  629. {  
  630.     int i;  
  631.     if(l==r)return;  
  632.     int mid=(l+r)>>1;  
  633.     int same=mid-l+1;//表示等于中间值而且被分入左边的个数  
  634.     for(i=l;i<=r;i++)  
  635.       if(tree[dep][i]
  636.          same--;  
  637.     int lpos=l;  
  638.     int rpos=mid+1;  
  639.     for(i=l;i<=r;i++)  
  640.     {  
  641.         if(tree[dep][i]//比中间的数小,分入左边  
  642.              tree[dep+1][lpos++]=tree[dep][i];  
  643.         else if(tree[dep][i]==sorted[mid]&&same>0)  
  644.         {  
  645.             tree[dep+1][lpos++]=tree[dep][i];  
  646.             same--;  
  647.         }  
  648.         else  //比中间值大分入右边  
  649.             tree[dep+1][rpos++]=tree[dep][i];  
  650.         toleft[dep][i]=toleft[dep][l-1]+lpos-l;//从1到i放左边的个数  
  651.   
  652.     }  
  653.     build(l,mid,dep+1);  
  654.     build(mid+1,r,dep+1);  
  655. }  
  656.   
  657. //查询区间第k小的数,[L,R]是大区间,[l,r]是要查询的小区间  
  658. //时间复杂度为O(log(N))  
  659. int query(int L,int R,int l,int r,int dep,int k)  
  660. {  
  661.     if(l==r)return tree[dep][l];  
  662.     int mid=(L+R)>>1;  
  663.     int cnt=toleft[dep][r]-toleft[dep][l-1];//[l,r]中位于左边的个数  
  664.     if(cnt>=k)  
  665.     {  
  666.         //L+要查询的区间前被放在左边的个数  
  667.         int newl=L+toleft[dep][l-1]-toleft[dep][L-1];  
  668.         //左端点加上查询区间会被放在左边的个数  
  669.         int newr=newl+cnt-1;  
  670.         return query(L,mid,newl,newr,dep+1,k);  
  671.     }  
  672.     else  
  673.     {  
  674.          int newr=r+toleft[dep][R]-toleft[dep][r];  
  675.          int newl=newr-(r-l-cnt);  
  676.          return query(mid+1,R,newl,newr,dep+1,k-cnt);  
  677.     }  
  678. }  
  679. Init()  
  680. {  
  681.      memset(toleft,0,sizeof(toleft));    
  682.      for(i=1;i<=n;i++)    
  683.      {   
  684.         scanf("%d",&tree[0][i]);   
  685.          sorted[i]=tree[0][i];   
  686.      }   
  687.       sort(sorted+1,sorted+n+1);    
  688.       build(1,n,0);   
  689. }  
  690. //*****************************************************************  
  691.   
  692. 字符串匹配  
  693. Manacher算法求最长回文子串  
  694. //*****************************************************************  
  695. const int MAXN=1000000+100;  
  696. char str1[MAXN*2],str2[MAXN*2];//待处理字符串  
  697. int num[MAXN*2];  
  698. //将str1变成str2,如abab变成$#a#b#a#b#  
  699. void init()  
  700. {  
  701.     int i,id;  
  702.     str2[0]='$';  
  703.     str2[1]='#';  
  704.     for(i=0,id=2;str1[i];i++,id+=2)  
  705.     {  
  706.         str2[id]=str1[i];  
  707.         str2[id+1]='#';  
  708.     }  
  709.     str2[id]=0;  
  710. }  
  711. //Manacher算法求最长回文子串,时间复杂度为O(N)  
  712. int Manacher()  
  713. {  
  714.     int i,ans=0,MxR=0,pos=1;  
  715.     for(i=1;str2[i];i++)  
  716.     {  
  717.         if(MxR>i)num[i]=num[pos*2-i]<(MxR-i)?num[pos*2-i]:(MxR-i);  
  718.         else num[i]=1;  
  719.         while(str2[i+num[i]]==str2[i-num[i]])  
  720.             num[i]++;  
  721.         if(num[i]+i>MxR)  
  722.         {  
  723.             MxR=num[i]+i;  
  724.             pos=i;  
  725.         }  
  726.         if(ans
  727.             ans=num[i];  
  728.     }  
  729.     return ans-1;  
  730. }  
  731. //*****************************************************************  
  732.   
  733. BF  
  734. //*****************************************************************  
  735. //BF算法查找str2是否是str1的子串,返回str2在str1中首元素的下标  
  736. int  BF()  
  737. {  
  738.     int i,j,len1,len2;  
  739.     len1=strlen(str1);  
  740.     len2=strlen(str2);  
  741.     i=0;j=0;  
  742.     while(i
  743.     {  
  744.         if(str1[i]==str2[j])  
  745.         {  
  746.             i++;  
  747.             j++;  
  748.         }  
  749.         else  
  750.         {  
  751.             i=i-j+1;  
  752.             j=0;  
  753.         }  
  754.     }  
  755.     if(j==len2)  
  756.         return i-j;  
  757.     else   
  758.         return -1;  
  759. }  
  760. //*****************************************************************  
  761.   
  762.   
  763. KMP  
  764. len % (len - next[len]) == 0,那么循环节的循环次数为len / (len - next[len]),否则为1  
  765. //*****************************************************************  
  766. char W[MAXN],T[MAXN];//W为模式串,T为主串  
  767. int next[MAXN];  
  768. //整个KMP算法时间复杂度为O(N+M)  
  769. //KMP算法中计算next[]数组  
  770. void getNext(char *p)  
  771. {  
  772.     int j,k,len=strlen(p);  
  773.     j=0;  
  774.     k=-1;  
  775.     next[0]=-1;  
  776.     while(j
  777.     {  
  778.         if(k==-1||p[j]==p[k])  
  779.         {  
  780.             next[++j]=++k;  
  781.         }  
  782.         else k=next[k];  
  783.     }  
  784. }  
  785. //KMP算法统计模式串W在主串T中出现的次数  
  786. int KMP_count(char *W,char *T)  
  787. {  
  788.     int i,wlen=strlen(W),tlen=strlen(T),j=0,ans=0;  
  789.     getNext(W);  
  790.     for(i=0;i
  791.     {  
  792.         while(j>0&&T[i]!=W[j])  
  793.           j=next[j];  
  794.         if(W[j]==T[i])j++;  
  795.         if(j==wlen)  
  796.         {  
  797.             ans++;  
  798.             j=next[j];  
  799.         }  
  800.     }  
  801.     return ans;  
  802. }  
  803. //返回模式串T在主串S中首次出现的位置  
  804. //返回的位置是从0开始的,若没有找到返回-1。  
  805. int KMP_Index(char *W,char *T)  
  806. {  
  807.     int i=0, j=0,wlen=strlen(W),tlen=strlen(T);  
  808.     getNext(W);  
  809.     while(i
  810.     {  
  811.         if(j==-1||T[i]==W[j])  
  812.         {  
  813.             i++; j++;  
  814.         }  
  815.         else  
  816.             j=next[j];  
  817.     }  
  818.     if(j==wlen)  
  819.         return i-wlen;  
  820.     else  
  821.         return -1;  
  822. }  
  823. //*****************************************************************  
  824.   
  825. 字符串的最小表示法  
  826. //*****************************************************************  
  827. //返回母串的最小子串的起始位置,返回值从1开始到strlen(str)  
  828. int minpresent(char *str)  
  829. {  
  830.     int i,j,k,len=strlen(str);  
  831.     i=0,j=1,k=0;  
  832.     while(i
  833.     {  
  834.         if(str[(i+k)%len]==str[(j+k)%len])  
  835.             k++;  
  836.         else   
  837.         {  
  838.             if(str[(i+k)%len]>str[(j+k)%len])  
  839.             i=i+k+1;  
  840.             else   
  841.             j=j+k+1;  
  842.             if(i==j)j++;  
  843.             k=0;  
  844.         }  
  845.     }  
  846.     return ++i<++j?i:j;  
  847. }  
  848. //*****************************************************************  
  849.   
  850. 字典树  
  851. //************************************************************  
  852. //定义字典树结构体  
  853. struct Trie  
  854. {  
  855.     Trie* next[26];  
  856.     int flag;  
  857. };  
  858. Trie *root;  
  859. //初始化root  
  860. void init()  
  861. {  
  862.     root=new Trie;  
  863.     memset(root,0,sizeof(Trie));  
  864. }  
  865. //2.插入  
  866. //将str插入以root为根节点的字典树中  
  867. void insert(char *str)  
  868. {  
  869.     int len = strlen(str);  
  870.     Trie *s = root;  
  871.     for (int i = 0; i < len; i++)  
  872.     {  
  873.         if (s->next[str[i] - 'a'])  
  874.             s = s->next[str[i] - 'a'];  
  875.         else  
  876.         {  
  877.             Trie* t = new Trie;  
  878.             memset(t, 0, sizeof (Trie));  
  879.             s->next[str[i] - 'a'] = t;  
  880.             s = t;  
  881.         }  
  882.     }  
  883.     s->flag = 1;  
  884. }  
  885. //3.查找  
  886. //查找字典树中是否有元素str  
  887. int find(char *str)  
  888. {  
  889.     int len = strlen(str);  
  890.     Trie *s = root;  
  891.     for (int i = 0; i < len; i++)  
  892.     {  
  893.         if (s->next[str[i] - 'a'])  
  894.             s = s->next[str[i] - 'a'];  
  895.         else  
  896.             return 0;  
  897.     }  
  898.     return s->flag;/////////////////////flag可能不标志为单词结尾  
  899. }  
  900. //5.释放内存空间  
  901. //释放以root为根节点的字典树内存空间  
  902. void del(Trie *root)  
  903. {  
  904.     Trie *s = root;  
  905.     for (int i = 0; i < 26; i++)  
  906.     {  
  907.         if (s->next[i])  
  908.             del(s->next[i]);  
  909.     }  
  910.     delete s;  
  911.     s = NULL;  
  912. }  
  913. //*****************************************************************  
  914.   
  915. AC自动机模板  
  916. //************************************************************  
  917. const int kind = 26;//视具体情况改动  
  918. struct node  
  919. {  
  920.     node *fail; //失败指针  
  921.     node *next[kind]; //Tire每个节点的26个子节点(最多26个字母)  
  922.     int count; //是否为该单词的最后一个节点  
  923.     node()  
  924.     { //构造函数初始化  
  925.         fail=NULL;  
  926.         count=0;  
  927.         memset(next,NULL,sizeof(next));  
  928.     }  
  929. }*q[1000*255]; //队列方便用于bfs构造失败指针,大小应依据Tries图//节点个数而定  
  930. int head,tail; //队列的头尾指针  
  931. node *Root;  
  932. //1.建立Tries  
  933. void insert(char *str,node *root)  
  934. //建立一颗以root为根节点的不带前缀指针的字典树  
  935. {  
  936.     node *p=root;  
  937.     int i=0,index;  
  938.     while(str[i])  
  939.     {  
  940.         index=str[i]-'A';//视具体情况改动  
  941.         if(p->next[index]==NULL)   
  942.             p->next[index]=new node();  
  943.         p=p->next[index];  
  944.         i++;  
  945.     }  
  946.     p->count=1;  
  947. }  
  948. //2.建立前缀指针,形成Tries图  
  949. void build_ac_automation(node *root)  
  950. //在建好的字典树上添加前缀指针,形成Tries图,即ac自动机  
  951. {  
  952.     int i;  
  953.     root->fail=NULL;  
  954.     q[head++]=root;  
  955.     while(head!=tail)  
  956.     {  
  957.         node *temp=q[tail++];  
  958.         node *p=NULL;  
  959.         for(i=0;i
  960.         {  
  961.             if(temp->next[i]!=NULL)  
  962.             {  
  963.                 if(temp==root)   
  964.                     temp->next[i]->fail=root;  
  965.                 else  
  966.                 {  
  967.                     p=temp->fail;  
  968.                     while(p!=NULL)  
  969.                     {  
  970.                         if(p->next[i]!=NULL)  
  971.                         {  
  972.                             temp->next[i]->fail=p->next[i];  
  973.                             break;  
  974.                         }  
  975.                         p=p->fail;  
  976.                     }  
  977.                     if(p==NULL)   
  978.                         temp->next[i]->fail=root;  
  979.                 }  
  980.                 q[head++]=temp->next[i];  
  981.             }  
  982.         }  
  983.     }  
  984. }  
  985. //3.查询母串  
  986. int query(node *root,char *s)  
  987. //有多少种模式串出现在母串str[]中  
  988. {  
  989.     int i=0,cnt=0,index,len=strlen(s);  
  990.     node *p=root;  
  991.     while(s[i])  
  992.     {  
  993.         index=s[i]-'A';//视具体情况改动  
  994.         while(p->next[index]==NULL && p!=root)  
  995.             p=p->fail;  
  996.         p=p->next[index];  
  997.         p=(p==NULL)?root:p;  
  998.         node *temp=p;  
  999.         while(temp!=root&&temp->count)  
  1000.         {  
  1001.             cnt+=temp->count;  
  1002.             temp->count=0;  
  1003.             temp=temp->fail;  
  1004.         }     
  1005.         i++;  
  1006.     }  
  1007.     return cnt;  
  1008. }  
  1009. //4.初始化  
  1010. void init()  
  1011. {  
  1012.     head=tail=0;  
  1013.     Root=new node;  
  1014. }  
  1015. //************************************************************  
  1016.   
  1017. 后缀数组  
  1018. //*****************************************************************  
  1019. const int MAXN=100000+100;  
  1020. char str[MAXN];//待处理字符串  
  1021. int sa[MAXN];//求得的后缀数组  
  1022. int wa[MAXN],wb[MAXN],wv[MAXN],wh[MAXN];  
  1023. int cmp(int *r,int a,int b,int l)  
  1024. {  
  1025.     return r[a]==r[b]&&r[a+l]==r[b+l];  
  1026. }  
  1027. //求后缀数组sa[],下标1到n-1(此处n=strlen(str)+1)有效后缀  
  1028. //将str的n个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入sa中。  
  1029. //保证Suffix(sa[i])  
  1030. //1<=i  
  1031. //倍增算法的时间复杂度为O(nlogn)  
  1032. //倍增算法的空间复杂度都是O(n)  
  1033. void da(char *r,int *sa,int n,int m)  
  1034. {  
  1035.     int i,j,p,*x=wa,*y=wb,*t;  
  1036.     for(i=0;i
  1037.     for(i=0;i
  1038.     for(i=1;i
  1039.     for(i=n-1;i>=0;i--) sa[--wh[x[i]]]=i;  
  1040.     for(j=1,p=1;p
  1041.     {  
  1042.         for(p=0,i=n-j;i
  1043.         for(i=0;iif(sa[i]>=j) y[p++]=sa[i]-j;  
  1044.         for(i=0;i
  1045.         for(i=0;i
  1046.         for(i=0;i
  1047.         for(i=1;i
  1048.         for(i=n-1;i>=0;i--) sa[--wh[wv[i]]]=y[i];  
  1049.         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i
  1050.             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;  
  1051.     }  
  1052.     return;  
  1053. }  
  1054.   
  1055. int rank[MAXN],height[MAXN];  
  1056. //定义height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公  
  1057. //共前缀,也就是排名相邻的两个后缀的最长公共前缀  
  1058. //任意两个起始位置为i,j(假设rank[i]  
  1059. //为height[rank[i]+1]、height[rank[i]+2]…height[rank[j]]的最小值  
  1060. void calheight(char *r,int *sa,int n)  
  1061. {  
  1062.     int i,j,k=0;  
  1063.     for(i=1;i<=n;i++) rank[sa[i]]=i;  
  1064.     for(i=0;i
  1065.         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);  
  1066.         return;  
  1067. }  
  1068.   
  1069. //求不可重叠最长重复子串  
  1070. //先二分答案,把题目变成判定性问题:判断是否  
  1071. //存在两个长度为k 的子串是相同的,且不重叠  
  1072. //时间复杂度为O(N*log(N))  
  1073. int Bin_Solve(int n)  
  1074. {  
  1075.     int i,Minlen,Maxlen,midlen,lowid,highid;  
  1076.     bool flag;  
  1077.     Minlen=0,Maxlen=n/2;  
  1078.     while(Minlen<=Maxlen)//二分重复字串的长度  
  1079.     {  
  1080.         midlen=(Minlen+Maxlen)/2;  
  1081.         lowid=n+1,highid=0;  
  1082.         flag=false;  
  1083.         for(i=1;i<=n&&!flag;i++)//此处i表示排名  
  1084.         {  
  1085.             if (height[i]//中间有一个的长度不大于midlen,就断开了  
  1086.             //即说明前面的和后面的最长公共前缀不可能大于等于miflen  
  1087.             else if(height[i]>=midlen)//长度大于等于midlen  
  1088.             {  
  1089.                 lowid=min(lowid,sa[i]);  
  1090.                 highid=max(highid,sa[i]);  
  1091.                 if(highid-lowid>=midlen)//且不重叠  
  1092.                     flag=true;  
  1093.             }  
  1094.         }  
  1095.         if(flag)Minlen=midlen+1;  
  1096.         else Maxlen=midlen-1;  
  1097.     }  
  1098.     return Maxlen<4?0:Maxlen+1;  
  1099. }  
  1100. //*****************************************************************  
  1101.   
  1102.   
  1103.                
  1104.                  4.图论  
  1105. 邻接表建图  
  1106. //*****************************************************  
  1107. const int MAXN=1000+100;  
  1108. const int INF = 0x3f3f3f3f;  
  1109.   
  1110. int head[MAXN];  
  1111. int dis[MAXN];  
  1112. bool visited[MAXN];  
  1113. int qq[MAXN];//模拟队列  
  1114. struct node  
  1115. {  
  1116.     int to;  
  1117.     int next;  
  1118. }Edg[20000+100];  
  1119. int n,m,tot;  
  1120.   
  1121. void init()  
  1122. {  
  1123.     tot=0;  
  1124.     memset(head,-1,sizeof(head));  
  1125. }  
  1126.   
  1127. void add(int a,int b)  
  1128. {  
  1129.     Edg[tot].to=b;  
  1130.     Edg[tot].next=head[a];  
  1131.     head[a]=tot++;  
  1132. }  
  1133.   
  1134. void BFS(int s)  
  1135. {  
  1136.     //queueqq;  
  1137.     //qq.push(s);  
  1138.     int front,rear;  
  1139.      front=rear=0;       
  1140.     qq[front++]=s;  
  1141.     int now,i,to;  
  1142.     for(i=1;i<=n;i++)  
  1143.     {  
  1144.         if(i!=s)dis[i]=INF;  
  1145.         else dis[i]=0;  
  1146.     }  
  1147.     visited[s]=true;  
  1148.     while(rear
  1149.     {  
  1150.         //now=qq.front();  
  1151.         //qq.pop();  
  1152.         now=qq[rear++];  
  1153.         for(i=head[now];i!=-1;i=Edg[i].next)  
  1154.         {  
  1155.             to=Edg[i].to;  
  1156.             if(to==now||visited[to])continue;  
  1157.             dis[to]=dis[now]+1;  
  1158.             //qq.push(to);  
  1159.             qq[front++]=to;  
  1160.             visited[to]=true;  
  1161.         }  
  1162.     }  
  1163. }  
  1164. //*****************************************************  
  1165.   
  1166.   
  1167.   
  1168. 二分图:  
  1169. 模板一:匈牙利算法  
  1170. //************************************************************  
  1171. //二分图匹配(匈牙利算法的DFS实现)  
  1172. //初始化:g[][]两边顶点的划分情况  
  1173. //建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配  
  1174. //g没有边相连则初始化为0  
  1175. //uN是匹配左边的顶点数,vN是匹配右边的顶点数  
  1176. //调用:res=hungary();输出最大匹配数  
  1177. //优点:适用于稠密图,DFS找增广路,实现简洁易于理解  
  1178. //时间复杂度:O(VE)  
  1179. //************************************************************  
  1180. //顶点编号从0开始的  
  1181. const int MAXN=510;  
  1182. int uN,vN;//u,v数目  
  1183. int g[MAXN][MAXN];  
  1184. int linker[MAXN];  
  1185. bool visited[MAXN];  
  1186. bool dfs(int u)//从左边开始找增广路径  
  1187. {  
  1188.     int v;  
  1189.     for(v=0;v//这个顶点编号从0开始,若要从1开始需要修改  
  1190.       if(g[u][v]&&!visited[v])  
  1191.       {  
  1192.           visited[v]=true;  
  1193.           if(linker[v]==-1||dfs(linker[v]))  
  1194.           {//找增广路,反向  
  1195.               linker[v]=u;  
  1196.               return true;  
  1197.           }  
  1198.       }  
  1199.     return false;//这个不要忘了,经常忘记这句  
  1200. }  
  1201. int hungary()  
  1202. {  
  1203.     int res=0;  
  1204.     int u;  
  1205.     memset(linker,-1,sizeof(linker));  
  1206.     for(u=0;u
  1207.     {  
  1208.         memset(visited,0,sizeof(visited));  
  1209.         if(dfs(u)) res++;  
  1210.     }  
  1211.     return res;  
  1212. }  
  1213. //****************************************************  
  1214.   
  1215.   
  1216. 最小生成树的Kruskal算法  
  1217. //************************************************************  
  1218. //带权值的无向图的最小生成树的Kruskal算法  
  1219. int id[maxm];//id[]存放边的下标,从[0-m-1]  
  1220. int eu[maxm],ev[maxm],ew[maxm];//依次存放无向边的两顶点和权值  
  1221. int n,m;//n为顶点数,m为边数  
  1222. int par[maxn];//并查集中存放顶点的数组  
  1223. int cmp( const int &i , const int &j)   
  1224. {   
  1225.     return ew[i]
  1226. }  
  1227. int Get_Par( int x)  
  1228. {  
  1229.     if( par[x]==x)  
  1230.         return par[x];  
  1231.     par[x]=Get_Par(par[x]) ;  
  1232.     return par[x] ;   
  1233. }  
  1234. int Kruskal( )  
  1235. {  
  1236.     int ret=0, i , j , p ;  
  1237.     for(i=1;i<=n;i++)  
  1238.         par[i]=i; // node [ 1 . . n ]  
  1239.     for(i=0;i
  1240.         id[i]=i ; // ew [ 0 . .m.1]  
  1241.     std::sort(id,id+m,cmp) ;  
  1242.     for(j=-1,i=1;i
  1243.     {  
  1244.         while(p=id[++j],Get_Par(eu[p])==Get_Par(ev[p]));  
  1245.         ret+=ew[p];  
  1246.         par[Get_Par(ev[p])]=Get_Par(eu[p]) ;  
  1247.     }  
  1248.     return ret;  
  1249. }  
  1250. //************************************************************  
  1251.   
  1252. Dijkstra算法  
  1253. //************************************************************  
  1254. #define INF 0x3f3f3f3f  
  1255. #define Max 155  
  1256. int n;//表示顶点数目  
  1257. int dis[Max];//dis数组表示源点到各点的距离  
  1258. int g[Max][Max];//用邻接矩阵g[][]存放图的边  
  1259. bool visited[Max];//标记原点到该点的最短距离是否找到  
  1260. //开始应初始化memset(g, INF, sizeof(g));  
  1261. void Dijkstra(int start)  
  1262. {  
  1263.     int temp,k,i,j;  
  1264.     memset(visited,false,sizeof(visited));  
  1265.     for(i=1;i<=n;++i)  
  1266.         dis[i]=g[start][i];  
  1267.     dis[start]=0;  
  1268.     visited[start]=1;  
  1269.     for(i=1;i<=n;++i)  
  1270.     {  
  1271.         temp=INF;  
  1272.         for(int j=1;j<=n;++j)  
  1273.             if(!visited[j]&&temp>dis[j])  
  1274.                 temp=dis[k=j];  
  1275.         if(temp==INF)break;  
  1276.         visited[k]=1;  
  1277.         for(j=1;j<=n;++j)  
  1278.             if(!visited[j]&&dis[j]>dis[k]+g[k][j])  
  1279.                 dis[j]=dis[k]+g[k][j];  
  1280.     }  
  1281. }  
  1282. //************************************************************  
  1283.   
  1284. flyod算法  
  1285. //*****************************************************************  
  1286. int const Max=1001;   
  1287. int a[Max][Max];//存放边的权值  
  1288. int b[Max];//存放顶点的权值  
  1289. int nex[Max][Max]; //next[i][j]用来保存i-->j的最短路径中i的最优后即最近的顶点  
  1290. int N;   
  1291. void floyd()  
  1292. //flyod算法求个顶点间的最短路径长度并记录路径  
  1293. {  
  1294.     int i,j,k,fee;   
  1295.       
  1296.     for(i=1;i<=N;i++)  
  1297.         for(j=1;j<=N;j++)  
  1298.             nex[i][j]=j;   
  1299.           
  1300.   
  1301.         for(k=1;k<=N;k++)  
  1302.         {  
  1303.             for(i=1;i<=N;i++)  
  1304.             {  
  1305.                 if(i==k||a[i][k]==-1)  
  1306.                     continue;  
  1307.                 for(j=1;j<=N;j++)  
  1308.                 {  
  1309.                     if(a[k][j]==-1||j==k)  
  1310.                         continue;   
  1311.                     fee = a[i][k]+a[k][j]+b[k];   
  1312.                     if(a[i][j]==-1||a[i][j]>fee)  
  1313.                     {  
  1314.                         a[i][j]=fee;   
  1315.                         nex[i][j]=nex[i][k];   
  1316.                     }  
  1317.                     //选择字典序小的路径  
  1318.                     else if(a[i][j]==fee)  
  1319.                     {  
  1320.                         if(nex[i][j]>nex[i][k])  
  1321.                             nex[i][j]=nex[i][k];  
  1322.                     }  
  1323.                 }  
  1324.             }  
  1325.         }  
  1326. }  
  1327.   
  1328. void path(int i, int j)  
  1329. //递归输出最短路径  
  1330. {  
  1331.     if(j==nex[i][j])  
  1332.     {  
  1333.         printf("%d-->%d\n",i,j);   
  1334.     }  
  1335.     else   
  1336.     {  
  1337.         printf("%d-->",i);   
  1338.         path(nex[i][j],j);    
  1339.     }  
  1340. }  
  1341. //*****************************************************************  
  1342.   
  1343.   
  1344.   
  1345.             数论  
  1346. 矩阵快速幂  
  1347. //*****************************************************  
  1348. //origin存放需计算的矩阵,res存放答案矩阵  
  1349. //最终答案为res.a[1][0](对应f[n])  
  1350. struct matrix  
  1351. {  
  1352.     __int64 a[2][2];  
  1353. };  
  1354. matrix origin,res;  
  1355. //将res初始化为初始条件矩阵,人为输入关系递推矩阵origin  
  1356. void init()  
  1357. {  
  1358.     origin.a[0][0]=1,origin.a[1][0]=origin.a[0][1]=1,origin.a[1][1]=0;  
  1359.     res.a[0][0]=1,res.a[0][1]=res.a[1][0]=res.a[1][1]=0;  
  1360. }  
  1361. //直接将2个矩阵相乘x*y,返回计算后的矩阵  
  1362. matrix multiply(matrix &x,matrix &y,__int64 MOD)  
  1363. {  
  1364.     matrix temp;  
  1365.     memset(temp.a,0,sizeof(temp.a));  
  1366.     for(int i=0;i<2;i++)  
  1367.     {  
  1368.         for(int j=0;j<2;j++)  
  1369.         {  
  1370.             for(int k=0;k<2;k++)  
  1371.             {  
  1372.                 temp.a[i][j]+=x.a[i][k]*y.a[k][j];  
  1373.                 temp.a[i][j]%=MOD;  
  1374.             }  
  1375.         }  
  1376.     }  
  1377.     return temp;  
  1378. }  
  1379. //矩阵快速幂的计算,矩阵的n次幂,每个中间结果对MOD取模  
  1380. void calc(matrix &origin,matrix &res,__int64 n,__int64 MOD)  
  1381. {  
  1382.     while(n)  
  1383.     {  
  1384.         if(n&1)  
  1385.             res=multiply(origin,res,MOD);  
  1386.         n>>=1;  
  1387.         origin=multiply(origin,origin,MOD);  
  1388.     }  
  1389. }  
  1390. //*****************************************************  
  1391.   
  1392. 快速幂  
  1393. A^B %C=A^( B%phi(C)+phi(C) ) %C     B>=phi(C)  
  1394. //************************************************************  
  1395. //快速幂x^n%mod的计算  
  1396. __int64 optimized_pow_n(__int64 x, __int64 n)  
  1397. {  
  1398.     __int64  pw = 1;  
  1399.     while (n > 0)  
  1400.     {  
  1401.         if (n & 1)         
  1402.             pw *= x;  
  1403.          pw=pw%mod;  
  1404.         x *= x;  
  1405.          x=x%mod;  
  1406.         n >>= 1;       
  1407.     }  
  1408.     return pw;  
  1409. }  
  1410. //************************************************************  
  1411.   
  1412. 三分法求凹凸函数的极值点  
  1413. //*****************************************************  
  1414. //当需要求某凸性或凹形函数的极值,通过函数本身表达式并不容易求解时,就可以用三分法不断逼近求解  
  1415. double mid, midmid;  
  1416. while ( low + eps < high )  
  1417. {  
  1418.     mid = (low + high) / 2;  
  1419.     midmid = (mid + high ) / 2;  
  1420.     double cmid = cal(mid);  
  1421.     double cmidmid = cal(midmid);  
  1422.     if ( cmid > cmidmid )   
  1423.             high = midmid;  
  1424.     else   
  1425.         low = mid;  
  1426. }  
  1427. //*****************************************************  
  1428.   
  1429. 普通母函数  
  1430. //*****************************************************  
  1431. //普通母函数,求组合数。  
  1432. int n,sum;//n表示物品种类数,sum为在[1,sum]范围类求每个价值的组合数(不排列)  
  1433. int num[100+10],value[100+10];//num[]存放该种类对应的个数,value[]存放该种类对应的价值  
  1434. int a[10000+100];  
  1435. int b[10000+100];  
  1436. void Generating_function()  
  1437. {  
  1438.     int i,j,k;  
  1439.     memset(a,0,sizeof(a));  
  1440.     memset(b,0,sizeof(b));  
  1441.     a[0]=1;  
  1442.     for(i=1;i<=n;i++)  
  1443.     {  
  1444.         for(j=0;j<=sum;j++)  
  1445.         {  
  1446.             for(k=0;k<=num[i]&&k*value[i]+j<=sum;k++)  
  1447.             {  
  1448.                 b[k*value[i]+j]+=a[j];  
  1449.                 b[k*value[i]+j]%=10000;  
  1450.             }  
  1451.         }  
  1452.         memcpy(a,b,sizeof(b));  
  1453.         memset(b,0,sizeof(b));  
  1454.     }  
  1455. }  
  1456. //*****************************************************  
  1457.   
  1458. 最大公约数  
  1459. //*****************************************************  
  1460. //求a,b的最大公约数  
  1461. LL Gcd(LL a,LL b)  
  1462. {  
  1463.     return b==0?a:Gcd(b,a%b);   
  1464. }   
  1465. //*****************************************************  
  1466.   
  1467.   
  1468.   
  1469.   
  1470.   
  1471.   
  1472.   
  1473.   
  1474.   
  1475.   
  1476.   
  1477.   
  1478. 计算几何  
  1479.   
  1480. //求不共线三点的外接圆,利用圆心到三点距离相等联立方程求得  
  1481. point GetCentre(point a,point b,point c)  
  1482. {  
  1483.     double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2;  
  1484.     double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2;  
  1485.     double d=a1*b2-a2*b1;  
  1486.     point ret;  
  1487.     ret.x=a.x+(c1*b2-c2*b1)/d;  
  1488.     ret.y=a.y+(a1*c2-a2*c1)/d;  
  1489.     return ret;  
  1490. }  
  1491.   
  1492.   
  1493. 头文件及宏定义  
  1494. #include  
  1495. #include  
  1496. #include  
  1497. #include  
  1498. #include  
  1499. #include  
  1500. #include  
  1501. #include  
  1502. #include  
  1503. #include  
  1504. #include  
  1505. #include  
  1506. #include  
  1507. #include  
  1508. #include  
  1509. #include  
  1510. #include  
  1511. #include  
  1512. #include    
  1513. using namespace std;  
  1514. const double eps(1e-8);  
  1515. const int INF = 0x3f3f3f3f;  
  1516. //优先级队列的两种定义方式  
  1517. struct cmp//对应大顶堆  
  1518. {  
  1519.     bool operator()(int a,int b)  
  1520.     {  
  1521.         return a
  1522.     }  
  1523. };  
  1524. priority_queue<int,vector<int>,cmp>Q;  
  1525.   
  1526. struct node  
  1527. {  
  1528.     int id;  
  1529.     bool operator < (const node& b)const   
  1530.     {  
  1531.         return id>b.id;  
  1532.     }  
  1533. };  
  1534. priority_queueQ;  
  1535.   
  1536.   
  1537. //set,multiset用法  
  1538. struct cmp  
  1539. {  
  1540.      bool operator ()(const node &a,const node &b)const   
  1541.      {  
  1542.         return a.nam//从小到大排序  
  1543.      }  
  1544. };  
  1545. multisetMulSet;//存放未处理 

你可能感兴趣的:(杂文)