codeforces 1202C (模拟,思维)

 开始觉得这道题是一个贪心发现每次操作很麻烦,一直到比赛结束也没想到什么好的办法。

 题意:

  有一个无限大的二维格子,从其中任意一点作为起点,按照所给的字符串WASD四个方向去移动,我们在字符串任意位置插入一个操作(WASD四个方向的一个),使走过方格所围成的矩形面积最小。

 题解:

  如果暴力考虑在某个位置插入的话,每次进行插入后再去检测这样时间复杂度会达到O(n2),很明显会超时。我们可以发现走过格子的高度不受左右变化的影响('A','D'操作不会对高度产生影响),同理宽度也不会被

上下方向所影响。

  现在单独考虑高度的最小值。我们默认从(0,0)开始,用一个数组sum将每一个操作走后的高度求出来。就会得到一个关于高度变化的序列。我们会发现这个序列中相邻的两个不同元素相差为1。还可以得到高度变化后的最大值和最小值。如果不进行任何变化那它的高度为 (max-min+1)。

  1. 当最后一个最大值出现在第一个最小值之前,我们就可以将最大值后面所有的值全部加1。因此后面所有的最小值全部加1。这样高度就会变为(max-min)。
  2. 当最后一个最小值出现在第一个最大值之前,我们就可以将最小值后面所有的值全部减1。因此后面所有的最大值全部减1。这样高度就会变为(max-min)。
  3. 当最后一个最大值前面有最小值,可以发现后面所有值加1后,前面仍有最小值,答案不会变小。
  4. 当最后一个最小值前面有最大值,可以发现后面所有值减1后,前面仍有最大值,答案不会减小。
  5. 当最大值与最小值<2时,我们没有去变化的空间,所以答案不能发生改变。

  综上所述,我们只要找到:最后一个最大值是否小于第一个最小值的位置且差值大于1或者最后一个最小值是否小于第一个最大值的位置且差值大于1就可以将答案缩小1。我们得出最小高度和最小宽度后,因为只能修改一次,我们只能修改高度或者宽度,所以要进行比较哪个更小。

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf = 0x3f3f3f3f;
 4 typedef long long ll;
 5 const ll mod = 998244353;
 6 char a[200010];
 7 int sum[2][200010],len;
 8 int result(int maxn,int minn,int z)
 9 {
10     if(maxn-minn<2)
11     {
12         return maxn-minn+1;
13     }
14     int maxfirst,maxsecond;
15     int minfirst,minsecond;
16     int flag1=0,flag2=0;
17     for(int i=0;i<=len;i++)
18     {
19         if(sum[z][i]==maxn&&flag1==0)
20         {
21             maxfirst=i;
22             flag1=1;
23         }
24         if(sum[z][i]==minn&&flag2==0)
25         {
26             minfirst=i;
27             flag2=1;
28         }
29         if(sum[z][i]==maxn)
30         {
31             maxsecond=i;
32         }
33         if(sum[z][i]==minn)
34         {
35             minsecond=i;
36         }
37     }
38     if(maxsecond+2<=minfirst)
39     {
40         return maxn-minn;
41     }
42     else if(minsecond+2<=maxfirst)
43     {
44         return maxn-minn;
45     }
46     else
47     {
48         return maxn-minn+1;
49     }
50 }
51 
52 int main()
53 {
54     ios::sync_with_stdio(false);
55     cin.tie(0),cout.tie(0);
56     int T;
57     cin>>T;
58     while(T--)
59     {
60         cin>>a;
61         len = strlen(a);
62         int maxn1=0,maxn2=0;
63         int minn1=0,minn2=0;
64         for(int i=0;i<len;i++)
65         {
66             sum[0][i+1]=sum[0][i];
67             sum[1][i+1]=sum[1][i];
68             if(a[i]=='W')
69             {
70                 sum[0][i+1]++;
71             }
72             else if(a[i]=='S')
73             {
74                 sum[0][i+1]--;
75             }
76             else if(a[i]=='A')
77             {
78                 sum[1][i+1]++;
79             }
80             else sum[1][i+1]--;
81             maxn1=max(maxn1,sum[0][i+1]);
82             maxn2=max(maxn2,sum[1][i+1]);
83             minn1=min(minn1,sum[0][i+1]);
84             minn2=min(minn2,sum[1][i+1]);
85         }
86         ll ans1=result(maxn1,minn1,0);
87         ll ans2=result(maxn2,minn2,1);
88         //cout<<ans1<<" "<<ans2<<endl;
89         ll ans= min(ans1*(maxn2-minn2+1),ans2*(maxn1-minn1+1));
90         cout<<ans<<endl;
91     }
92     return 0;
93 }
View Code

 

posted on 2019-09-15 14:58  闻声  阅读(216)  评论(0编辑  收藏  举报