[考试反思]0415省选模拟71:限制

奇奇怪怪的一场考试。状态还是有点差。

一看$T2$这$30000$的数据范围就知道大概可以$n^2$卡过。

然后纠结了半天到底要想正解还是卡暴力。于是又花了好长时间想正解然而什么都没想出来。

于是就开始卡暴力,的确卡的挺快的但是细节挂了一处丢了$40pts$。

在靠后也是除了牛逼以外跑得最快的。然而并没有什么用,$WA$了就没啥好说的。

结果犹犹豫豫磨磨叽叽等$T2$弄完时间也就不多了。于是$T1/3$只好定位为暴力。

过程中$T1$的正解在脑中一闪而过然而并没有花时间继续想(也没那个时间了)

最后$T1$的暴力不明原因$50$挂成$40$。$T3$的$15pts$暴力莫名其妙拿到了$30pts$

就这样了。就是仨题炸了俩。暴力写的倒是挺全。时间分配炸掉了。

 

T1:王子

大意:$n$点序列,每个点有$A_i,B_i$两种权值,要求每个点选择一种权值满足任意连续$k$个点中至少$P$个$A$权值至少$Q$个$B$权值。最大化权值和。$n \le 200$

数据范围闻上去像网络流的味道

每个节点代表一个长为$k$的区间然后把这些点串起来,原图里的每个点作为一条边驾在它所对应的最左/右的区间之间。

无源汇上下界最大费用可行流。带正环,所以只要像你钦定下界一样钦定正边满流,调整度数并建反边就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 5555
 4 int n,k,A,B,ans,T,fir[S],l[S],to[S],d[S],v[S],w[S],ec=1,q[S],iq[S],al[S];
 5 void link(int a,int b,int V,int W){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;v[ec]=V;w[ec]=W;}
 6 void con(int a,int b,int V,int W=0){
 7     if(W<=0)link(a,b,V,W),link(b,a,0,-W);
 8     else link(a,b,0,W),link(b,a,V,-W),ans+=W,d[a]++,d[b]--;
 9 }
10 bool bfs(){
11     for(int i=1;i<=T;++i)d[i]=-998244353;
12     for(int h=1,t=1;h<=t;iq[q[h]]=0,++h)for(int i=fir[q[h]];i;i=l[i])if(d[to[i]]<d[q[h]]+w[i]&&v[i]){
13         d[to[i]]=d[q[h]]+w[i];
14         if(!iq[to[i]])q[++t]=to[i];
15     }return d[T]!=-998244353;
16 }
17 int dfs(int p,int f){int r=f;
18     if(p==T)return f; al[p]=1;
19     for(int i=fir[p];i&&r;i=l[i])if(!al[to[i]]&&d[to[i]]==d[p]+w[i]&&v[i]){
20         int x=dfs(to[i],min(r,v[i]));
21         if(!x)d[to[i]]=-998244353;
22         ans+=w[i]*x; v[i]-=x; v[i^1]+=x; r-=x;
23     }al[p]=0;return f-r;
24 }
25 int main(){
26     cin>>n>>k>>A>>B; T=n-k+3; d[1]=B; d[T-1]=-B;
27     for(int i=1,x,e;i<=n;++i)scanf("%d%d",&x,&e),ans+=x,con(min(n-k+2,i+1),max(1,i-k+1),1,e-x);
28     for(int i=1;i<T-1;++i)con(i,i+1,k-A-B);
29     for(int i=1;i<T;++i)if(d[i]<0)con(0,i,-d[i]);else con(i,T,d[i]);
30     while(bfs())dfs(0,n);
31     cout<<ans<<endl;
32 }
View Code

 

T2:遇见

大意:求满足(出现过的数出现次数都是奇数)的子区间个数。$n \le 30000$

暴力卡常直接过。

我加剪枝了:如果这个数目前出现了偶数次且没有下一次出现则直接跳过。

然后我还把连续的同一种数压在了一起。就过去了。

正解的话,随机化,给每种颜色随机一个权值然后问题就是求异或和为$0$的区间个数。

枚举右端点,考虑权值变化。并不会修改,分块+$trie$就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[33333],n,N,Ans;bool nxt[33333];short lst[1000005],cnt[1000005],t[33333];
 4 int main(){
 5     scanf("%d",&n);
 6     for(int i=1;i<=n;++i){
 7         N++;
 8         scanf("%d",&a[N]);
 9         if(a[N]==a[N-1])N--;
10         else nxt[lst[a[N]]]=1,lst[a[N]]=N;
11         t[N]++;
12     }
13     for(int i=1;i<=N;++i){
14         register int R=N,z=0,ans=0;
15         for(int j=i;j<=R;++j){
16             if(z==0)ans+=cnt[a[j]]?t[j]>>1:t[j]+1>>1;
17             else if(z==1&&cnt[a[j]]&&(cnt[a[j]]&1)==0)ans+=t[j]+1>>1;
18             z-=cnt[a[j]]&&(cnt[a[j]]&1)==0;
19             cnt[a[j]]+=t[j];
20             z+=(cnt[a[j]]&1)==0;
21             if(!nxt[j]&&(cnt[a[j]]&1)==0)R=j;
22         }for(int j=i;j<=R;++j)cnt[a[j]]-=t[j];
23         for(int j=t[i]&1?1:2;j<=t[i];j+=2)Ans+=ans,ans--;
24         if(t[i]==1)continue;
25         t[i]--;ans=z=0;R=N;
26         for(int j=i;j<=R;++j){
27             if(z==0)ans+=cnt[a[j]]?t[j]>>1:t[j]+1>>1;
28             else if(z==1&&cnt[a[j]]&&(cnt[a[j]]&1)==0)ans+=t[j]+1>>1;
29             z-=cnt[a[j]]&&(cnt[a[j]]&1)==0;
30             cnt[a[j]]+=t[j];
31             z+=(cnt[a[j]]&1)==0;
32             if(!nxt[j]&&(cnt[a[j]]&1)==0)R=j;
33         }for(int j=i;j<=R;++j)cnt[a[j]]-=t[j];
34         for(int j=t[i]&1?1:2;j<=t[i];j+=2)Ans+=ans,ans--;
35     }cout<<Ans<<endl;
36 }
View Code

 

T3:字符串

大意:给出$n$个模式串满足其$trie$节点$\le 50$,给定匹配串支持以下操作:

询问子区间$[l,r]$中模式串出现次数和。将子区间$[l,r]$循环赋值为$str$(就是把$str$复制若干遍覆盖$[l,r]$)$|S|,Q,\sum |str| \le 10^5$

题目提示的已经很明显了是$AC$自动机。

区间修改能想到的就是线段树。

我们对线段树每个节点维护$t[i]$表示在线段树左端点进入之前匹配到$AC$自动机的节点$i$的话那么加入区间的字符串之后会匹配到$t[i]$。

并且维护$w[i]$表示过程中出现的模式串个数。

可以拿到没有修改的部分分以及可以暴力修改的部分分。

然后我们对于每个$str$维护一个$g[a][b][c][d]$表示对于第$a$个修改操作对应的$str$从其第$b$位开始走$2^c$位,最开始从$AC$自动机$d$结点出发最后到了哪里以及贡献

就可以倍增了。

为了方便我们把线段树最开始的大小重置为$2$的整次幂,那么这个倍增数据就可以直接得到一个节点的值。

时间复杂度大约是$O(Qlog\ n |S|)$这级别的。

时空都要注意,千万别$vector$。$g$的$a,b$可以压成一维就不用$vector$了。我蠢的一批还写了个内存池。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 1<<20
 4 int fail[55],c[55][27],q[55],n,Q,v[55],W[55],pc,rt,mi[S]; char s[S];
 5 int lz[S],w[S][51],t[S][51],len,lp,ans,lend[S],cnt,lenth[S],bit,pool[1<<28],SIZE;
 6 void insert(int&p,int l){
 7     if(!p)p=++pc;
 8     if(!s[l]){v[p]++;return;}
 9     insert(c[p][s[l]-'a'],l+1);
10 }
11 struct ST{
12     int bgv,bge,st1,st2;
13     int&v(int a,int b,int c){return pool[bgv+a*st1+b*st2+c];}
14     int&e(int a,int b,int c){return pool[bge+a*st1+b*st2+c];}
15     void init(){
16         int l=lenth[++cnt]=strlen(s);
17         st2=l; st1=l*(pc+1); bgv=SIZE; SIZE+=st1*(bit+1); bge=SIZE; SIZE+=st1*(bit+1);
18         for(int j=0;j<l;++j)for(int i=1;i<=pc;++i)
19             v(0,i,j)=c[i][s[j]-'a'],e(0,i,j)=W[v(0,i,j)];
20         for(int i=1;i<=bit;++i)for(int j=0;j<l;++j)for(int k=1;k<=pc;++k)
21             v(i,k,j)=v(i-1,v(i-1,k,j),(j+(1<<i-1))%l),
22             e(i,k,j)=e(i-1,v(i-1,k,j),(j+(1<<i-1))%l)+e(i-1,k,j);
23     }
24 }R;vector<ST>st;
25 #define lc p<<1
26 #define rc lc|1
27 #define md (L+R>>1)
28 void up(int p){for(int i=1;i<=pc;++i)t[p][i]=t[rc][t[lc][i]],w[p][i]=w[lc][i]+w[rc][t[lc][i]];}
29 void build(int p,int L,int R){
30     if(L==R){
31         if(R<=len)for(int i=1;i<=pc;++i)t[p][i]=c[i][s[L]-'a'],w[p][i]=W[c[i][s[L]-'a']];
32         return;
33     }build(lc,L,md);build(rc,md+1,R); up(p);
34 }
35 void cov(int p,int L,int R,int o){
36     int B=mi[R-L+1],z=(L-lend[o])%lenth[o]; lz[p]=o;
37     for(int i=1;i<=pc;++i)t[p][i]=st[o].v(B,i,z),w[p][i]=st[o].e(B,i,z);
38 }
39 void down(int p,int L,int R){cov(lc,L,md,lz[p]);cov(rc,md+1,R,lz[p]);lz[p]=0;}
40 void ask(int l,int r,int p=1,int L=1,int R=n){
41     if(l<=L&&R<=r){ans+=w[p][lp];lp=t[p][lp];return;}
42     if(lz[p])down(p,L,R);
43     if(l<=md)ask(l,r,lc,L,md); if(r>md)ask(l,r,rc,md+1,R);
44 }
45 void mdf(int l,int r,int p=1,int L=1,int R=n){
46     if(l<=L&&R<=r){cov(p,L,R,cnt); return;}
47     if(lz[p])down(p,L,R);
48     if(l<=md)mdf(l,r,lc,L,md); if(r>md)mdf(l,r,rc,md+1,R); up(p);
49 }
50 int main(){//freopen("ex_string2.in","r",stdin);freopen("0.out","w",stdout);
51     for(int i=0;i<=19;++i)mi[1<<i]=i;
52     cin>>n>>Q; st.push_back(R);
53     for(int i=1;i<=n;++i)cin>>s,insert(rt,0);
54     q[1]=1; fail[0]=1;
55     for(int i=0;i<26;++i)c[0][i]=1;
56     for(int h=1,t=1;h<=t;++h)for(int j=0;j<26;++j)
57         if(c[q[h]][j])fail[q[++t]=c[q[h]][j]]=c[fail[q[h]]][j];
58         else c[q[h]][j]=c[fail[q[h]]][j];
59     for(int i=1;i<=pc;++i)for(int j=i;j;j=fail[j])W[i]+=v[j];
60     scanf("%s",s+1); len=strlen(s+1);n=1;
61     while(n<len)n<<=1,bit++; build(1,1,n);
62     while(Q--){
63         int op,x,y;scanf("%d%d%d",&op,&x,&y);
64         if(op==2)lp=1,ans=0,ask(x,y),printf("%d\n",ans);
65         else scanf("%s",s),R.init(),st.push_back(R),mdf(lend[cnt]=x,y);
66     }
67 }
View Code

 

posted @ 2020-04-15 22:24  DeepinC  阅读(203)  评论(0编辑  收藏  举报