Atcoder 077E - guruguru(线段树+dp)

题目链接: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\n",ans);
91     return 0;
92 }

 

posted @ 2017-07-18 15:03  7391_KID  阅读(246)  评论(0编辑  收藏  举报