Codeforces1198B Welfare State(分块)

题目链接:http://codeforces.com/problemset/problem/1198/B

题目大意:n个数据,q个操作,每个操作有两种情况,一种是将某一个数据改为x,另一种是将所有小于x的数据改为x。所有操作结束后输出数组。

这道题是我第一次在非练习(就是那种半天一题磨洋工状态)情况下用分块解决了题目,所以写篇详解纪念一下。

这道题大佬们的写法貌似不是分块emmmm,也对,根据题目输出的特殊性或许有别的办法,但蒟蒻我目前能想到的只有分块了。(莽过了就好)

思路就是用一个mi数组记录每个块的最小值,一个mark数组记录该块是否被修改过(详细解释见下)。

显然的,对于第二种操作,如果某个块的最小值大于x,那我们就不用对这个块进行操作。反之,我们把这个块的最小值标为x,并且让这个块的mark置1。然后,对于mark置1的块,如果我们的操作1访问到它了,就遍历一次块,将每个<=x的数改为x,再进行修改。

输出的时候只要注意判断一下mark的状态就行了。最坏的情况两种修改的复杂度都是O根号n。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<set>
 4 #include<stdio.h>
 5 #include<string.h>
 6 #include<math.h>
 7 #include<vector>
 8 #include<stdlib.h>
 9 #include<queue>
10 #include<algorithm>
11 #include<map>
12 #include<stack>
13 using namespace std;
14 int a[200005];
15 int bl[200005];
16 int blo;
17 int mi[2005];//每个块的最小值
18 int mark[2005];//标记状态
19 int le[2005];//每个块的左边界
20 int ri[2005];//每个块的右边界
21 int main()
22 {
23     int n;
24     scanf("%d",&n);
25     blo=sqrt(n);
26     memset(mi,-1,sizeof(mi));
27     for(int i=1;i<=n;i++)
28     {
29         scanf("%d",&a[i]);
30         bl[i]=(i-1)/blo+1;
31         if(mi[bl[i]]==-1||a[i]<mi[bl[i]])
32         {
33             mi[bl[i]]=a[i];
34         }
35         if(le[bl[i]]==0)
36         {
37             le[bl[i]]=i;
38         }
39         ri[bl[i]]=i;
40     }
41     int q;
42     memset(mark,-1,sizeof(mark));
43     scanf("%d",&q);
44     int k,p,x;
45     while(q--)
46     {
47         scanf("%d",&k);
48         if(k==1)
49         {
50             scanf("%d%d",&p,&x);
51             if(mark[bl[p]]==1)
52             {
53                 for(int i=le[bl[p]];i<=ri[bl[p]];i++)
54                 {
55                     if(a[i]<mi[bl[p]])
56                     {
57                         a[i]=mi[bl[p]];
58                     }
59                 }
60                 mark[bl[p]]=-1;
61             }
62             a[p]=x;
63             if(x<mi[bl[p]])
64             {
65                 mi[bl[p]]=x;
66             }
67         }
68         else
69         {
70             scanf("%d",&x);
71             for(int i=1;i<=bl[n];i++)
72             {
73                 if(mi[i]>=x)
74                 {
75                     continue;
76                 }
77                 else
78                 {
79                     mi[i]=x;
80                     mark[i]=1;
81                 }
82             }
83         }
84     }
85     for(int i=1;i<=n;i++)
86     {
87         if(mark[bl[i]]==-1||a[i]>=mi[bl[i]])
88         {
89             printf("%d%c",a[i],i==n?'\n':' ');
90         }
91         else
92         {
93             printf("%d%c",mi[bl[i]],i==n?'\n':' ');
94         }
95     }
96     return 0;
97 }

 

posted @ 2019-07-31 10:26  虚在君  阅读(228)  评论(0编辑  收藏  举报