您的位置:首页 > 其它

CodeForces–833B--The Bakery(线段树&&DP)

2017-08-16 22:02 417 查看
B. The Bakerytime limit per test2.5 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard output
1 /*
2 * @FileName: D:\代码与算法\2017训练比赛\CF#426\b-pro.cpp
3 * @Author: Pic
4 * @Date:   2017-08-16 19:51:14
5 * @Last Modified time: 2017-08-16 21:57:55
6 */
7
8 #include<bits/stdc++.h>
9 using namespace std;
10 const int INFINITE = INT_MAX;
11 const int MAXN=35000+30;
12 const int MAXNUM = MAXN*4+30;
13 struct SegTreeNode
14 {
15     int val;
16     int addMark;//延迟标记
17 }segTree[MAXNUM];//定义线段树
18
19 /*
20 功能:当前节点的标志域向孩子节点传递
21 root: 当前线段树的根节点下标
22 */
23 void pushDown(int root)
24 {
25     if(segTree[root].addMark != 0)
26     {
27         //设置左右孩子节点的标志域,因为孩子节点可能被多次延迟标记又没有向下传递
28         //所以是 “+=”
29         segTree[root*2+1].addMark += segTree[root].addMark;
30         segTree[root*2+2].addMark += segTree[root].addMark;
31         //根据标志域设置孩子节点的值。因为我们是求区间最小值,因此当区间内每个元
32         //素加上一个值时,区间的最小值也加上这个值
33         segTree[root*2+1].val += segTree[root].addMark;
34         segTree[root*2+2].val += segTree[root].addMark;
35         //传递后,当前节点标记域清空,防止多次向下传递,造成数据错误
36         segTree[root].addMark = 0;
37     }
38 }
39
40 /*
41 功能:线段树的区间查询
42 root:当前线段树的根节点下标
43 [nstart, nend]: 当前节点所表示的区间
44 [qstart, qend]: 此次查询的区间
45 */
46 int query(int root, int nstart, int nend, int qstart, int qend)
47 {
48     //查询区间和当前节点区间没有交集
49     if(qstart > nend || qend < nstart)
50         return -1;
51     //当前节点区间包含在查询区间内
52     if(qstart <= nstart && qend >= nend)
53         return segTree[root].val;
54     //分别从左右子树查询,返回两者查询结果的较小值
55     pushDown(root); //----延迟标志域向下传递(在向下递归之前,首先将延迟标志域向下传递)
56     int mid = (nstart + nend) / 2;
57     return max(query(root*2+1, nstart, mid, qstart, qend),
58                query(root*2+2, mid + 1, nend, qstart, qend));
59
60 }
61
62 /*
63 功能:更新线段树中某个区间内叶子节点的值
64 root:当前线段树的根节点下标
65 [nstart, nend]: 当前节点所表示的区间
66 [ustart, uend]: 待更新的区间
67 addVal: 更新的值(原来的值加上addVal)
68 */
69 void update(int root, int nstart, int nend, int ustart, int uend, int addVal)
70 {
71     //更新区间和当前节点区间没有交集
72     if(ustart > nend || uend < nstart)
73         return ;
74     //当前节点区间包含在更新区间内
75     if(ustart <= nstart && uend >= nend)
76     {
77         segTree[root].addMark += addVal;
78         segTree[root].val += addVal;    //最小值当然也加1
79         return ;
80     }
81     pushDown(root); //延迟标记向下传递(在向下递归之前,首先将延迟标志域向下传递)
82     //更新左右孩子节点
83     int mid = (nstart + nend) / 2;
84     update(root*2+1, nstart, mid, ustart, uend, addVal);
85     update(root*2+2, mid+1, nend, ustart, uend, addVal);
86     //根据左右子树的值回溯更新当前节点的值
87     segTree[root].val = max(segTree[root*2+1].val, segTree[root*2+2].val);
88 }
89 int a[MAXN],last[MAXN],pre[MAXN];
90 int dp[MAXN];
91 void build(int root,int nstart,int nend)
92 {
93 	segTree[root].addMark=0;
94 	if(nstart==nend){
95 		segTree[root].val=dp[nstart-1];
96 		return ;
97 	}
98 	int mid=(nstart+nend)/2;
99 	build(root*2+1,nstart,mid);
100 	build(root*2+2,mid+1,nend);
101 }
102 int main(){
103 	//freopen("data.in","r",stdin);
104 	int n,k;
105 	scanf("%d%d",&n,&k);
106 		for(int i=1;i<=n;i++){
107 			scanf("%d",&a[i]);
108 			pre[i]=last[a[i]];
109 			last[a[i]]=i;
110 		}
111 		for(int j=1;j<=k;j++){
112 			build(0,0,n);
113 			for(int i=1;i<=n;i++){
114 				update(0,0,n,pre[i]+1,i,1);
115 				dp[i]=query(0,0,n,0,i);
116 			}
117 		}
118 		printf("%d\n",dp
);
119     return 0;
120 }


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: