ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[Comet1790]Ternary String Counting

2021-10-26 15:02:21  阅读:164  来源: 互联网

标签:String int Comet1790 位置 define while Counting 复杂度 getchar


令$f_{i,j,k}$表示前$i$个位置,三种字符最后一次出现的位置为$i,j$和$k$(保证$k<j<i$)的方案数

考虑转移(递推),即分为两步——

1.填写第$i$个字符,即从$f_{i-1,j,k}$转移到$f_{i,j,k},f_{i,i-1,j}$或$f_{i,i-1,k}$

2.考虑以$i$为右端点的区间,即仅保留$j\in [L_{j}(i),R_{j}(i)]$且$k\in [L_{k}(i),R_{k}(i)]$的位置(其余位置清0)

(关于$L/R_{j/k}(i)$显然可以$o(m)$预处理出)

暴力转移复杂度为$o(n^{3})$,考虑优化——

关于第一步,如果将$i$滚动,实际上修改的位置仅有$o(n)$个,而修改的值即某行/列的元素和,那么再额外维护该信息,同时修改也可以继续维护,复杂度降为$o(n^{2})$

关于第二步,注意到一个位置被清0后不会再有值,那么只需要快速找到需要清0且非0的位置,这可以对每行维护一个双向队列来实现,进而均摊复杂度也降为$o(n^{2})$

最终,总复杂度为$o(n^{2}+m)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 5005 
 4 #define mod 1000000007
 5 deque<int>q[N];
 6 int t,n,m,l,r,x,ans,Lj[N],Rj[N],Lk[N],Rk[N],sr[N],sc[N],f[N][N];
 7 int read(){
 8     int x=0;
 9     char c=getchar();
10     while ((c<'0')||(c>'9'))c=getchar();
11     while ((c>='0')&&(c<='9')){
12         x=x*10+c-'0';
13         c=getchar();
14     }
15     return x;
16 }
17 void upd(int x,int y,int z){
18     q[y].push_back(x);
19     sr[x]=(sr[x]+z)%mod;
20     sc[y]=(sc[y]+z)%mod;
21     f[x][y]=(f[x][y]+z)%mod;
22 }
23 void clear_l(int y){
24     int x=q[y].front();
25     q[y].pop_front();
26     sr[x]=(sr[x]-f[x][y]+mod)%mod;
27     sc[y]=(sc[y]-f[x][y]+mod)%mod;
28     f[x][y]=0;
29 }
30 void clear_r(int y){
31     int x=q[y].back();
32     q[y].pop_back();
33     sr[x]=(sr[x]-f[x][y]+mod)%mod;
34     sc[y]=(sc[y]-f[x][y]+mod)%mod;
35     f[x][y]=0;
36 }
37 int main(){
38     t=read();
39     while (t--){
40         n=read(),m=read();
41         for(int i=1;i<=n;i++){
42             Lj[i]=Lk[i]=0;
43             Rj[i]=Rk[i]=i-1;
44         }
45         for(int i=1;i<=m;i++){
46             l=read(),r=read(),x=read();
47             if (x==1)Rj[r]=min(Rj[r],l-1);
48             if (x==2)Lj[r]=max(Lj[r],l),Rk[r]=min(Rk[r],l-1);
49             if (x==3)Lk[r]=max(Lk[r],l);
50         }
51         memset(sr,0,sizeof(sr));
52         memset(sc,0,sizeof(sc));
53         memset(f,0,sizeof(f));
54         for(int i=0;i<n;i++)q[i].clear();
55         upd(0,0,1);
56         for(int i=1;i<=n;i++){
57             for(int j=0;j<max(i-1,1);j++)upd(i-1,j,(sr[j]+sc[j])%mod);
58             for(int j=0;j<i;j++){
59                 if ((Lk[i]<=j)&&(j<=Rk[i])){
60                     while ((!q[j].empty())&&(q[j].front()<Lj[i]))clear_l(j);
61                     while ((!q[j].empty())&&(q[j].back()>Rj[i]))clear_r(j);
62                 }
63                 else{
64                     while (!q[j].empty())clear_l(j);
65                 }
66             }
67         }
68         ans=0;
69         for(int i=0;i<n;i++)
70             for(int j=0;j<n;j++)ans=(ans+f[i][j])%mod;
71         printf("%d\n",ans);
72     }
73     return 0;
74 }
View Code

 

标签:String,int,Comet1790,位置,define,while,Counting,复杂度,getchar
来源: https://www.cnblogs.com/PYWBKTDA/p/15465789.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有