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; 
 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章