前言
“今天早上出地铁站的时候自动扶梯发生故障,我被困在上面一个多小时,所以迟到了。”欢迎来到嘟嘟课堂。今天,嘟嘟老师讲一道 ——石子游戏。
题目描述
你在桌子上放白和黑两种颜色的石子,第i个石子放在左边第i个位置,一共放了N个石子,当你放第i个石子必须遵循以下规则:
1.当i是奇数时:直接放在左数第i个位置上;
2.当i是偶数时:如果第i个石子和第i-1个石子颜色相同,直接放在第i个位置上;否则把当前最右边的连续的颜色相同的石子全部用相反颜色的石子取代,然后在第i个位置上放下石子i。
例如,假设桌子上现状是:○○●●○○○(○代表白石子,●代表黑石子)
如果第8个石子是白色,因为它和第7个石子颜色相同,就直接放在最右边就可以了,桌面上变成:○○●●○○○○;
如果第8个石子是黑的,因为和第7个颜色不同,就先把右边连续的3个白石子用黑石子代替,然后再放下第8个石子,变成:○○●●●●●●。
写一个程序,给你每个石子的颜色,输出最终桌面上白石子的数量。
输入
第一行输入一个整数N(1<=N<=100,000),接下来N行每行一个数C,表示N个石子的颜色,0表示白色,1表示黑色。
输出
输出一个整数表示最终白石子的数量。
样例输入1
8
1
0
1
1
0
0
0
0
样例输出1
6
样例输入2
8
1
0
1
1
0
0
0
1
样例输出2
2
数据范围限制
50%的N<=10000
思路
这道题是一道典型的区间题。一个区间,存数量和颜色,边读入边改颜色和总答案。就是把所有石子分成k个区间,每次要改变颜色的时候就把上一个区间的颜色给改了就行了,后面统计有几个区间是白的,把这几个区间的石子数量加起来就行了。中间还需要合并区间,如果第i个区间和第i-1个区间是同颜色的,就要把它们合并,因为在下一次的改颜色时,是要将前面所有不同颜色的所有的石子(直到遇到同颜色的石子)都改了。很多人就是忘记合并只得了20分。
其中D[I,1】表示第i个区间的头指针,D[I,2】是尾指针(这个区间是从D[I,1]到D[I,2]的,长度为D[I,2]-D[I,1]+1),D[I,3]表示这个区间的颜色。
代码
var
a:array[1..100000] of integer;
d:array[1..100000,1..3] of longint;
i,j,n,ans,k:longint;
begin
assign(input,'stone.in');reset(input);
assign(output,'stone.out');rewrite(output);
read(n);
d[0,3]:=2;
k:=0;
for i:=1 to n do
begin
read(a[i]);
if (a[i]<>d[k,3]) then
begin
if (i mod 2=0) then
begin
d[k,2]:=d[k,2]+1;
d[k,3]:=a[i];
if (d[k,3]=d[k-1,3]) then
begin
d[k-1,2]:=d[k,2];
dec(k);
end;
end
else
begin
inc(k);
d[k,1]:=i;
d[k,2]:=i;
d[k,3]:=a[i];
end;
end
else d[k,2]:=d[k,2]+1;
end;
for i:=1 to k do
if (d[i,3]=0) then ans:=ans+d[i,2]-d[i,1]+1;
write(ans);
close(input);
close(output);
end.