noip11 string

这道题改题时我打了个玄学复杂度的暴力,然后成功的时间最短,内存最小,然后我成功的造了一组数据hack掉了自己的代码。。。。

通过观察,我们可以很容易的发现在操作几次后,整个序列就会变成一块一块相同的字母。

于是我们可以对我们的暴力做一些优化:在将字母塞进桶中时,不是一个一个往里塞,而是将一段连续的区间O(1)塞进桶中。

实现也很简单:在每次操作后,存下每个块的左右端点,塞进去的时候注意把包含l,r的块断开,即可愉快的AC并且代码跑的快的飞起。

但是有一个问题:处理l,r所在块的边界时,需要暴力找到这两个块的边界,如果块特别大,那么每次寻找都是O(n)的,然后就愉快的T了(反正我自己造的100000个a跑了6s)

附超快AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline long long read()
 4 {
 5     int x=0,f=1;
 6     char ch=getchar();
 7     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8     while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
 9     return x*f;
10 }
11 int n,m,pre[100005],la,tong[27],a[100005],ne[100005],sum;
12 char s[100005];
13 int main()
14 {
15     n=read(),m=read();
16     cin>>s+1;
17     memset(a,-1,sizeof(a));
18     la=1,a[1]=s[1]-'a';
19     for(int i=2;i<=n;i++)
20         if(s[i]==s[i-1])
21             ne[i]=0;
22         else ne[la]=i-1,la=i,a[i]=s[i]-'a';
23     ne[la]=n;
24     for(int kk=1;kk<=m;kk++)
25     {
26         int l=read(),r=read(),x=read(),laa;
27         if(!ne[r+1]&&r!=n)
28             for(int i=r;i;i--)
29                 if(ne[i])
30                 {
31                     ne[r+1]=ne[i];
32                     a[r+1]=a[i];
33                     ne[i]=r;
34                     break;
35                 }
36         for(int i=l;i;i--)
37             if(ne[i])
38             {
39                 laa=ne[i]+1;
40                 tong[a[i]]=laa-l;
41                 if(i!=l)ne[i]=l-1;
42                 break;
43             }
44         while(laa<=r)
45         {
46             tong[a[laa]]+=min(ne[laa],r)-laa+1;
47             int nex=min(ne[laa],r);
48             ne[laa]=0,a[laa]=-1,laa=nex+1;
49         }
50         if(x==0)
51             for(int i=25;i>=0;i--)
52                 if(tong[i])
53                 {
54                     a[l]=i;
55                     ne[l]=l+tong[i]-1;
56                     l+=tong[i];
57                     tong[i]=0;
58                 }
59         if(x==1)
60             for(int i=0;i<=25;i++)
61                 if(tong[i])
62                 {
63                     a[l]=i;
64                     ne[l]=l+tong[i]-1;
65                     l+=tong[i];
66                     tong[i]=0;
67                 }
68     }
69     for(int i=1;i<=n;i++)
70     {
71         if(a[i]==-1)
72             a[i]=a[i-1];
73         putchar(a[i]+'a');
74     }
75     puts("");
76     return 0;
77 }
1.4k 766msAC

猜你喜欢

转载自www.cnblogs.com/hzoi-cbx/p/11285466.html