codeforces 278Div1 B题

虚拟参赛的时候没想到是线段树,看到很多人都过了,也蛮着急的。

首先用二分+线段树的方法更新DP[i]:它表示以A[i]为结尾可以最前到哪个位置;

再用线段树计算ans[i]:它表示当前i个A元素可以最少分成多少个pieces,ans[i]=1+min(ans[j]),dp[i]-1<=j<=i-L。

over.

16 #define N 100000+5
 17 
 18 int a[N],dp[N],Ans[N];
 19 struct segment {
 20     int l,r;
 21     int Min,Max,ans;
 22 } seg[4*N];
 23 
 24 struct diff {
 25     int Max,Min;
 26     diff(int x=0,int n=0):Max(x),Min(n) {}
 27 };
 28 
 29 void build(int p,int l,int r)
 30 {
 31     seg[p].l=l, seg[p].r=r, seg[p].ans=-1;;
 32     if (l==r) {
 33         seg[p].Min = seg[p].Max = a[l];
 34         return;
 35     }
 36     build(p<<1,l,(l+r)>>1);
 37     build((p<<1)+1,((l+r)>>1)+1,r);
 38 
 39     seg[p].Min = min(seg[p<<1].Min, seg[(p<<1)+1].Min),
 40     seg[p].Max = max(seg[p<<1].Max, seg[(p<<1)+1].Max);
 41 }
 42 
 43 diff query1(int p,int l,int r)
 44 {
 45     if (l<=seg[p].l && seg[p].r<=r) {
 46         return diff(seg[p].Max,seg[p].Min);
 47     }
 48 
 49     diff t1,t2;
 50     bool f1=false, f2=false;
 51     if (seg[p<<1].r>=l)
 52         f1=true, t1=query1(p<<1,l,r);
 53     if (seg[(p<<1)+1].l<=r)
 54         f2=true, t2=query1((p<<1)+1,l,r);
 55 
 56     if (f1) {
 57         if (f2)
 58             return diff(max(t1.Max,t2.Max), min(t1.Min,t2.Min));
 59         else
 60             return t1;
 61     }
 62     else
 63         if (f2)
 64             return t2;
 65     return diff(0,0);
 66 }
 67 
 68 int query2(int p,int l,int r)
 69 {
 70     if (l<=seg[p].l && seg[p].r<=r) {
 71         return seg[p].ans;
 72     }
 73 
 74     int t1=-1,t2=-1;
 75     if (seg[p<<1].r>=l)
 76         t1=query2(p<<1,l,r);
 77     if (seg[(p<<1)+1].l<=r)
 78         t2=query2((p<<1)+1,l,r);
 79 
 80     if (t1==-1) {
 81         return t2;
 82     }
 83     else {
 84         if (t2==-1)
 85             return t1;
 86         else return min(t1,t2);
 87     }
 88 
 89 }
 90 
 91 void add(int p,int i,int newans)
 92 {
 93     if (seg[p].l==seg[p].r) {
 94         seg[p].ans=newans;
 95         return;
 96     }
 97 
 98     if (i<=seg[p<<1].r)
 99         add(p<<1,i,newans);
100     else
101         add((p<<1)+1,i,newans);
102 
103     if (seg[p<<1].ans==-1) {
104         seg[p].ans = seg[(p<<1)+1].ans;
105     }
106     else {
107         if (seg[(p<<1)+1].ans==-1)
108             seg[p].ans=seg[p<<1].ans;
109         else
110             seg[p].ans=min(seg[p<<1].ans,seg[(p<<1)+1].ans);
111     }
112 }
113 
114 int main()
115 {
116     //freopen("b.txt","r",stdin);
117 
118     int n,s,l;
119     cin>>n>>s>>l;
120     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
121     build(1,1,n);
122     for (int i=1;i<=n;i++) {
123         int L=1,R=i-1;
124         dp[i]=i;
125         while (L<=R) {
126             int mid = (L+R)>>1;
127             diff tmp = query1(1,mid,i);
128             if (tmp.Max-tmp.Min<=s) {
129                 R=mid-1;
130                 dp[i]=mid;
131             }
132             else {
133                 L=mid+1;
134             }
135         }
136     }
137 
138 
139     for (int i=1;i<=n;i++) {
140         if (i<l) {
141             Ans[i]=-1;
142             continue;
143         }
144         int tmp=-1;
145         if (i-l>0 && dp[i]-1<=i-l)
146             tmp=query2(1,max(1,dp[i]-1),i-l);
147         if (dp[i]==1) tmp=0;
148 
149         if (tmp==-1)
150             Ans[i]=-1;
151         else
152             Ans[i]=tmp+1, add(1,i,Ans[i]);
153     }
154     cout<<Ans[n]<<endl;
155 
156     return 0;
157 }
原文地址:https://www.cnblogs.com/nuaalida/p/4129407.html