Code Chef Sereja and Subsegment Increasings

最近连续被构造题坑,希望能借这些题好好总结(区间统一修改,差分是永恒的主题!!)

考虑每个数至少需要多少次操作,c1[i]=(b[i]-a[i]+4)%4,当然,如果进行c[i]=c1[i]+4*e次操作也能符合条件;

假设我们已经知道了要每个钟要操作多少次,那么要通过多少次区间操作完成?

差分,值为\sum \left ( c[i]-c[i+1] \right ) [1<i<N][c[i]-c[i+1]>0]

这个可以画张图考虑,把每个值看做坐标轴上的长方形,每次只能取一个区间高度为1的长方形

若左边长方形高度<右边长方形高度,只要在取右边长方形时顺便取一下即可(不用加次数)

若左边长方形高度>右边长方形高度,高的长度肯定要单独取

 

因此我们只要找到一种方案  c[i]使其zhi=\sum \left ( c[i]-c[i+1] \right ) [1<i<N][c[i]-c[i+1]>0]最小即可

先不考虑给c[i]加上4,答案就是zhi=\sum \left ( c[i]-c[i+1] \right ) [1<i<N][c[i]-c[i+1]>0]

考虑  k[i]=c[i]-c[i-1]

现在考虑如果对(l,r]加上4,那么有影响的只有kl和kr,

k[l]-4,k[r]+4。

如果k[l]=0那么不用考虑,因为答案不可能变小,(因为最初时这两个点对值的贡献为0+k[r],现在为0+k[r]+4,不减反增)

如果k[l]=1,也不用考虑。(因为最初时这两个点对值的贡献为1+k[r],现在为0+k[r]+4,不减反增)

如果k[l]=2,当k[r]=-3,答案会变小1(因为最初时这两个点对值的贡献为2+0,现在为0+1)

如果k[l]=3,当k[r]=-3,答案会变小2,(因为最初时这两个点对值的贡献为3+0,现在为0+1)  (因为这个贡献大于下一个,所以在匹配                                                                                                                                                               时先要考虑这个)

                 当k[r]=-2时,答案会变小1(因为最初时这两个点对值的贡献为3+0,现在为0+1)

所以我们只要从1~n不断地把-3跟2或3匹配,-2跟3匹配即可。

如何匹配(这里条件比较简单,用小技巧解决),比较复杂时用dp

 

#include<bits/stdc++.h>
using namespace std;
long long n,d2,d3,tot,zhi,a[2000000],b[2000000];
inline int read(){
    int out=0,flag=1;char c=getchar();
    while(c<48||c>57) {if(c=='-') flag=-1;c=getchar();}
    while(c>=48&&c<=57){out=out*10+c-48;c=getchar();}
    return out*flag;
}
int main()
{	  n=read();
	  for (int i=1;i<=n;i++)
	  a[i]=read();
	  for (int i=1;i<=n;i++)
	  {
	  b[i]=read();
      a[i]=(b[i]-a[i]+4)%4;
	  }
	  //for (int i=1;i<=n;i++)
	  //cout<<a[i]<<' ';  cout<<endl;
	  for (int i=1;i<=n;i++)  a[i]=a[i]-a[i+1];
	  //for (int i=1;i<=n;i++)
	  //cout<<a[i]<<' ';
	  //cout<<endl;
      for (int i=1;i<=n;i++)
      {  if (a[i]>0)  tot+=a[i];   
	     if (a[i]==2)  d2++;
	     if (a[i]==3)  d3++;
	     if (a[i]==-3)  {  if (d3>0) {d3--;tot=tot-2;}
		                  else if (d2>0) {d2--; tot=tot-1;}
						}
		 if (a[i]==-2) { if (d3>0) {d3--;tot=tot-1;d2++;}} 	//匹配小技巧:如果之后有-3以匹配-2,相当于还能再减1			
      }
      cout<<tot<<endl; 
 
}

猜你喜欢

转载自blog.csdn.net/zzrh2018/article/details/81782339