题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_c
分析:如果某条线段包含x,显然应该先按一下到x,再从x走,反之必然是直接走过去,很容易想到用dp做,记len[i]为包含i点的线段长度之和,s[i]为以i为起点的线段数目,con[i]为包含i的线段数目,t[i]为以i为终点的线段数目,可以推出
dp[i+1]=dp[i]+len[i]+s[i]-con[i+1]-t[i]+s[i+1],输入时将需要的数字预处理好,con用线段树区间修改下,总的复杂度为O(nlogm+m)。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e5+5; 7 int n,m; 8 ll s[maxn],len[maxn],dp[maxn],t[maxn]; 9 class segTree{ 10 int a[maxn],s[maxn*4],lazy_tag[maxn*4]; 11 public: 12 segTree(){ 13 memset(a,0,sizeof(a)); 14 } 15 void build(int node,int begin,int end){ 16 lazy_tag[node]=0; 17 if(begin==end){ 18 s[node]=a[begin]; 19 }else{ 20 build(2*node,begin,(begin+end)/2); 21 build(2*node+1,(begin+end)/2+1,end); 22 s[node]=s[2*node]+s[2*node+1]; 23 } 24 } 25 int query(int k){ 26 return a[k]; 27 } 28 void PushDown(int node,int begin,int end){ 29 if(begin==end){ 30 s[node]+=lazy_tag[node]; 31 a[begin]=s[node]; 32 }else{ 33 lazy_tag[2*node]+=lazy_tag[node]; 34 lazy_tag[2*node+1]+=lazy_tag[node]; 35 } 36 s[node]+=lazy_tag[node]*(end-begin+1); 37 lazy_tag[node]=0; 38 } 39 void Change(int node,int begin,int end,int left,int right,int num){ 40 if(begin>=left&&end<=right){ 41 lazy_tag[node]+=num; 42 }else{ 43 PushDown(node,begin,end); 44 int m=(begin+end)/2; 45 if(!(left>m||right<begin)) 46 Change(2*node,begin,m,left,right,num); 47 if(!(left>end||right<m+1)) 48 Change(2*node+1,m+1,end,left,right,num); 49 } 50 } 51 void PushDown_all(int node,int begin,int end){ 52 PushDown(node,begin,end); 53 if(begin!=end){ 54 PushDown_all(2*node,begin,(begin+end)/2); 55 PushDown_all(2*node+1,(begin+end)/2+1,end); 56 } 57 } 58 }contain; 59 int main(){ 60 //freopen("e:\in.txt","r",stdin); 61 memset(s,0,sizeof(s)); 62 memset(t,0,sizeof(t)); 63 memset(dp,0,sizeof(dp)); 64 memset(len,0,sizeof(len)); 65 int a,b; 66 scanf("%d%d",&n,&m); 67 contain.build(1,1,m); 68 scanf("%d",&a); 69 for(int i=1;i<n;i++){ 70 s[a]++; 71 scanf("%d",&b); 72 t[b]++; 73 len[b]+=(b-a+m)%m; 74 if(b>a){ 75 contain.Change(1,1,m,a,b,1); 76 }else{ 77 contain.Change(1,1,m,1,b,1); 78 contain.Change(1,1,m,a,m,1); 79 } 80 dp[1]+=min((b-a+m)%m,1+(b-1+m)%m); 81 a=b; 82 } 83 contain.PushDown_all(1,1,m); 84 for(int i=1;i<m;i++){ 85 dp[i+1]=dp[i]+len[i]-t[i]+s[i]-contain.query(i+1)+s[i+1]; 86 } 87 ll ans=dp[1]; 88 for(int i=2;i<=m;i++) 89 ans=min(ans,dp[i]); 90 printf("%lld ",ans); 91 return 0; 92 }