省选模拟6&7

因为改题太慢,两篇总结合一块写了。

馍旎6:

抄了一套UR(的题目

A. Yist

根号算法。

首先判-1即为判断是否有一个点能对其他点作贡献,且不存在于s序列中。

考虑单个点的贡献,假如第一轮贡献为$a$,之后每一轮的的贡献即为$a*2^{cnt}$

cnt为这个点在序列中出现的次数。然后这玩意拿等比数列求和就可以了。

然后出题人随便造个菊花图就能卡死你。

考虑根号算法,按每个点度数是否大于$\sqrt{n}$分为大点和小点。

对于每个大点,统计时暴力扫与它相连的大点统计贡献,

大点同时累计自己对周围小点的贡献

小点暴力扫所有出边统计贡献,同时接受大点贡献

 1 #include<bits/stdc++.h>
 2 #define N 400050
 3 #define pb push_back
 4 const int mod=998244353,inv2=499122177;
 5 using namespace std;
 6 int s[N],n,m,k;
 7 int w[N],d[N];
 8 int a[N],ts[N],val[N];
 9 vector<int>v[N],c[N];
10 inline int qpow(int d,int z){
11     int ret=1;
12     for(;z;z>>=1,d=1ll*d*d%mod)
13         if(z&1)ret=1ll*ret*d%mod;
14     return ret;
15 }
16 inline bool judge(){
17     static bool pd[N];
18     memset(pd,false,sizeof(pd));
19     for(int i=1;i<=k;++i)pd[s[i]]=1;
20     for(int i=1;i<=n;++i)
21         for(int j=v[i].size()-1;~j;--j)
22             if(pd[i]&&!pd[v[i][j]]&&w[v[i][j]])
23                 return true;
24     return false;
25 }
26 bool cmp(const int &a,const int &b){
27     return v[a].size()>v[b].size();
28 }
29 int main(){
30     for(int i=1;i<=n;++i){
31         v[i].clear();c[i].clear();
32         ts[i]=1;a[i]=val[i]=d[i]=0;
33     }
34     if(scanf("%d%d%d",&n,&m,&k)==EOF)return 0;
35     for(int i=1;i<=n;++i){
36         scanf("%d",&w[i]);
37         v[i].clear();c[i].clear();
38         ts[i]=1,a[i]=val[i]=d[i]=0;
39     }
40     for(int i=1;i<=k;++i)scanf("%d",&s[i]);
41     for(int i=1,x,y;i<=m;++i){
42         scanf("%d%d",&x,&y);
43         v[x].pb(y);v[y].pb(x);
44     }
45     if(judge()){puts("-1");return main();}
46     const int sq=sqrt(n);
47     for(int i=1;i<=n;++i){
48         sort(v[i].begin(),v[i].end(),cmp);
49         d[i]=v[i].size()>=sq?1:0;
50     }
51     for(int i=1;i<=n;++i)
52         if(!d[i]){
53             for(int j=0,sz=v[i].size();j<sz&&d[v[i][j]];++j)
54                 c[i].pb(0);
55         }
56     int ans=0;
57
58     for(int i=1,g;i<=k;++i){
59         g=s[i];ts[g]<<=1;
60         if(ts[g]>=mod)ts[g]-=mod;
61         if(d[g]){
62             ++val[g];
63             for(int j=0,sz=v[g].size();j<sz&&d[v[g][j]];++j)
64                 (a[v[g][j]]+=w[v[g][j]])%=mod;
65         }
66         else{
67             for(int j=0,sz=v[g].size();j<sz;++j){
68                 (a[v[g][j]]+=w[v[g][j]])%=mod;
69                 if(d[v[g][j]]){
70                     (a[g]+=1ll*w[g]*(val[v[g][j]]-c[g][j])%mod)%=mod;
71                     c[g][j]=val[v[g][j]];
72                 }
73             }
74         }
75         w[g]=1ll*w[g]*inv2%mod;
76     }
77     for(int g=1;g<=n;++g)
78         if(!d[g]){
79             for(int j=0,sz=v[g].size();j<sz&&d[v[g][j]];++j)
80                 (a[g]+=1ll*w[g]*(val[v[g][j]]-c[g][j])%mod)%=mod;
81         }
82     for(int i=1;i<=n;++i){
83         ans+=1ll*a[i]*ts[i]%mod*qpow(ts[i]-1,mod-2)%mod;
84         if(ans>=mod)ans-=mod;
85     }
86     cout<<ans<<endl;
87     return main();
88 }

B. Ernd

$SAM+dp$

在串前加字符相当于在$parent_tree$上走,在串后加字符相当于在$SAM$上走。

发现对于$parent_tree$上一个节点,一定是把它先走到当前点的最大长度再转移。

拓扑dp,最后输出$dp[las]$

 1 #include<bits/stdc++.h>
 2 #define N 400050
 3 #define ull unsigned long long
 4 using namespace std;
 5 int n,f[N];
 6 int du[N];
 7 long long dp[N],ans;
 8 char s[N];
 9 int tot=1,las=1;
10 int he[N],ne[N],to[N],cnt;
11 inline void addedge(int x,int y){
12     to[++cnt]=y;ne[cnt]=he[x];he[x]=cnt;
13 }
14 struct node{
15     int len,fa;
16     int ch[26];
17 }tr[N];
18 inline void add(int c){
19     int np=++tot,p=las;las=np;f[np]=1;
20     tr[np].len=tr[p].len+1;
21     for(;p&&!tr[p].ch[c];p=tr[p].fa)tr[p].ch[c]=np;
22     if(!p)return tr[np].fa=1,void();
23     int q=tr[p].ch[c];
24     if(tr[q].len==tr[p].len+1)return tr[np].fa=q,void();
25     int nq=++tot;tr[nq]=tr[q];
26     tr[nq].len=tr[p].len+1;
27     tr[q].fa=tr[np].fa=nq;
28     for(;p&&tr[p].ch[c]==q;p=tr[p].fa)tr[p].ch[c]=nq;
29 }
30 inline void tope(){
31     for(int i=1;i<=tot;++i)
32         for(int j=0;j<26;++j)
33             ++du[tr[i].ch[j]];
34     queue<int>q;q.push(1);
35     while(q.size()){
36         int g=q.front();q.pop();
37 //        printf("f[%d]=%d\n",g,f[g]);
38         dp[g]=max(dp[g],dp[tr[g].fa]+f[g]*(tr[g].len-tr[tr[g].fa].len));
39         for(int i=0,t;i<26;++i){
40             t=tr[g].ch[i];if(!t)continue;
41             dp[t]=max(dp[t],dp[g]+1ll*f[t]*(tr[t].len-tr[g].len));
42             --du[t];
43             if(!du[t])q.push(t);
44         }
45     }
46     ans=dp[las];
47 }
48 inline void dfs(int g){
49     for(int i=he[g];i;i=ne[i])
50         dfs(to[i]),f[g]+=f[to[i]];
51 }
52 int main(){
53     scanf("%d%s",&n,s+1);
54     for(int i=1;i<=n;++i)add(s[i]-‘a‘);
55     for(int i=2;i<=tot;++i)addedge(tr[i].fa,i);
56     dfs(1);
57     tope();
58     cout<<ans<<endl;
59     return 0;
60 }

C. Sanrd

大神题,改了一下午加一晚上加一早上才改过来。

其实还是挺好理解的,就是代码难打

  1 #include<bits/stdc++.h>
  2 #define N 500050
  3 #define ull long long
  4 const int mod=998244353;
  5 using namespace std;
  6 int dp1[N],dp2[N],n,a[N],an1,an2,pr[N][2],pre[N];
  7 ull f[N],f2[N],al,w[N][2];
  8 struct BIT{
  9     int ct[N],po[N];
 10     inline void clear(){
 11         memset(ct,0,sizeof(int)*(n+1));
 12         memset(po,0,sizeof(int)*(n+1));
 13     }
 14     inline void add(int x,int v,int id=0){
 15         while(x){
 16             if(v>ct[x])
 17                 ct[x]=v,po[x]=id;
 18             x-=x&-x;
 19         }
 20     }
 21     inline int ask(int x){
 22         int ret=0;
 23         while(x<=n)
 24             ret=max(ret,ct[x]),x+=x&-x;
 25         return ret;
 26     }
 27     inline int ask2(int x){
 28         int ret=0,r2=0;
 29         while(x<=n){
 30             if(ct[x]>ret)ret=ct[x],r2=po[x];
 31             x+=x&-x;
 32         }
 33         return r2;
 34     }
 35 }b;
 36 struct BIT2{
 37     ull ct[N];int tim[N],cnt;
 38     inline void clear(){++cnt;}
 39     inline void add(int x,int v){
 40         while(x){
 41             if(tim[x]!=cnt)tim[x]=cnt,ct[x]=0;
 42             ct[x]+=v;x-=x&-x;
 43         }
 44     }
 45     inline ull ask(int x){
 46         ull ret=0;
 47         while(x<=n){
 48             if(tim[x]!=cnt)tim[x]=cnt,ct[x]=0;
 49             ret+=ct[x];
 50             x+=x&-x;
 51         }
 52         ret%=mod;
 53         return ret;
 54     }
 55 }b2;
 56 vector<int>v[N];
 57 #define pb push_back
 58 inline void init1(){
 59     b.clear();
 60     for(int i=1;i<=n;++i){
 61         dp2[i]=b.ask(a[i])+1;
 62         an2=max(an2,dp2[i]);
 63         b.add(a[i],dp2[i]);
 64         v[dp2[i]].push_back(i);
 65 //        printf("dp2[%d]=%d\n",i,dp2[i]);
 66     }
 67     for(int i=0,sz=v[an2].size();i<sz;++i)f[v[an2][i]]=1;
 68     for(int i=an2;i>1;--i){
 69         int j=v[i-1].size()-1,k=v[i].size()-1;
 70         b2.clear();
 71         while(j>=0){
 72             while(k>=0&&v[i][k]>v[i-1][j]){
 73                 b2.add(a[v[i][k]],f[v[i][k]]);
 74                 --k;
 75             }
 76             f[v[i-1][j]]=b2.ask(1)-b2.ask(a[v[i-1][j]]);
 77             if(f[v[i-1][j]]<0)f[v[i-1][j]]+=mod;
 78             --j;
 79         }
 80     }
 81 //    for(int i=1;i<=n;++i)printf("f[%d]=%lld f2:%lld\n",i,f[i],f2[i]);
 82     for(int i=0,sz=v[1].size();i<sz;++i)f2[v[1][i]]=1;
 83     for(int i=1;i<an2;++i){
 84         int j=0,k=0,sz=v[i].size(),sz2=v[i+1].size();
 85         b2.clear();
 86         while(j<sz2){
 87             while(k<sz&&v[i][k]<v[i+1][j]){
 88                 b2.add(a[v[i][k]],f2[v[i][k]]);
 89                 ++k;
 90             }
 91             f2[v[i+1][j]]=b2.ask(a[v[i+1][j]]);
 92             f[v[i+1][j]]*=f2[v[i+1][j]];
 93             f[v[i+1][j]]%=mod;
 94             ++j;
 95         }
 96     }
 97     for(int j=0,sz=v[an2].size();j<sz;++j)al+=f[v[an2][j]];
 98     al%=mod;
 99 //    for(int i=1;i<=n;++i)printf("f[%d]=%lld f2:%lld\n",i,f[i],f2[i]);
100 //    cout<<"al:"<<al<<endl;
101 }
102 int pd[N];
103 struct BIT3{
104     int ct[N];
105     inline void add(int x,int v){
106         while(x<=n){
107             if(v>ct[x])ct[x]=v;
108             x+=x&-x;
109         }
110     }
111     inline int ask(int x){
112         int ret=0;
113         while(x)ret=max(ret,ct[x]),x-=x&-x;
114         return ret;
115     }
116 }b3;
117 struct BIT4{
118     int q[N][2],ct[N];
119     ull qq[N][2];
120     inline void init(){
121         for(int i=1;i<=n;++i)qq[i][0]=qq[i][1]=q[i][0]=q[i][1]=-1;
122     }
123     inline void add(int i){
124         int x=a[i];
125         while(x<=n){
126             if(dp1[i]>ct[x]){
127                 ct[x]=dp1[i];
128                 q[x][0]=qq[x][0]=q[x][1]=qq[x][1]=-1;
129             }
130             if(ct[x]==dp1[i]&&qq[x][0]<0&&w[i][0]>=0){
131                 q[x][0]=i;
132                 qq[x][0]=w[i][0];
133                 if(w[i][1]>=0){
134                     q[x][1]=i;
135                     qq[x][1]=w[i][1];
136                 }
137             }
138             else if(ct[x]==dp1[i]&&qq[x][1]<0){
139                 if(w[i][0]>=0&&w[i][0]!=qq[x][0]){
140                     q[x][1]=i;
141                     qq[x][1]=w[i][0];
142                 }
143                 if(w[i][1]>=0&&w[i][1]!=qq[x][0]){
144                     q[x][1]=i;
145                     qq[x][1]=w[i][1];
146                 }
147             }
148             x+=x&-x;
149         }
150     }
151     inline void ask(int i){
152         int x=a[i];
153         while(x){
154             if(ct[x]==dp1[i]-1&&w[i][0]<0&&qq[x][0]>=0){
155                 pr[i][0]=q[x][0];
156                 w[i][0]=qq[x][0];
157                 if(qq[x][1]>=0){
158                     pr[i][1]=q[x][1];
159                     w[i][1]=qq[x][1];
160                 }
161             }
162             else if(ct[x]==dp1[i]-1&&w[i][1]<0&&qq[x][0]>=0){
163                 if(qq[x][0]>=0&&qq[x][0]!=w[i][0]){
164                     pr[i][1]=q[x][0];
165                     w[i][1]=qq[x][0];
166                 }
167                 if(qq[x][1]>=0&&qq[x][1]!=w[i][0]){
168                     pr[i][1]=q[x][1];
169                     w[i][1]=qq[x][1];
170                 }
171             }
172             x-=x&-x;
173         }
174     }
175 }b4;
176 inline void init2(){
177     b4.init();
178     for(int i=1;i<=n;++i){
179         dp1[i]=b3.ask(a[i])+1;
180         an1=max(an1,dp1[i]);
181         b3.add(a[i],dp1[i]);
182 //        printf("dp1[%d]=%d\n",i,dp1[i]);
183     }
184     for(int i=1;i<=n;++i){
185         w[i][0]=w[i][1]=-1;
186         //if(dp1[i]!=1)
187         b4.ask(i);
188         if(w[i][0]>=0||dp1[i]==1){
189             w[i][0]+=f[i];
190             if(dp1[i]==1)++w[i][0];
191         }
192         if(w[i][1]>=0)w[i][1]+=f[i];
193         w[i][0]%=mod;w[i][1]%=mod;
194 //        printf("i:%d w0:%lld w1:%lld p0:%d p1:%d\n",i,w[i][0],w[i][1],pr[i][0],pr[i][1]);
195         b4.add(i);
196     }
197 }
198 inline void dfs2(int g){
199     if(!g)return;dfs2(pre[g]);
200     printf("%d ",g);
201 }
202 inline void getans(){
203     b.clear();
204     printf("%d\n",an1);
205     for(int i=1;i<=n;++i){
206         dp2[i]=0;
207         if(pd[i]){
208             printf("%d ",i);
209             continue;
210         }
211         dp2[i]=b.ask(a[i])+1;
212         pre[i]=b.ask2(a[i]);
213         b.add(a[i],dp2[i],i);
214 //        printf("pre[%d]=%d dp2:%d\n",i,pre[i],dp2[i]);
215     }
216     printf("\n%d\n",an2);
217     for(int i=1;i<=n;++i)
218         if(dp2[i]==an2)return dfs2(i);
219 }
220 inline void dfs(int g,ull t){
221     if(!g)return getans();
222     pd[g]=1;
223     if((t+w[g][0])%mod!=al)dfs(pr[g][0],(t+f[g])%mod);
224     else dfs(pr[g][1],(t+f[g])%mod);
225 }
226 int main(){
227 //    freopen("sanrd2.in","r",stdin);freopen("my.out","w",stdout);
228     scanf("%d",&n);
229     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
230     init1();init2();
231     memset(pd,0,sizeof(int)*(n+1));
232     for(int i=1;i<=n;++i){
233 //        cout<<i<<" "<<w[i][0]<<" "<<w[i][1]<<endl;
234         if(dp1[i]==an1){
235             if(w[i][0]!=-1&&w[i][0]!=al){
236                 pd[i]=1;dfs(pr[i][0],f[i]);
237                 return 0;
238             }
239             if(w[i][1]!=-1&&w[i][1]!=al){
240                 pd[i]=1;dfs(pr[i][1],f[i]);
241                 return 0;
242             }
243         }
244     }
245     puts("-1");return 0;
246 }

馍旎7:

A. 翻转硬币/星空

原来写过一遍的题,然而也忘得差不多了。

用到了差分的思想。

考虑维护原01序列的差分序列。

则原先的区间操作对应新的对有距离限制的两个点取反,

转化为求最少多少次操作使得差分序列全为0。

然后对每个为1点求出与其它为1的点的距离。

然后跑状压dp就可以了。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<queue>
 5 #define reg register
 6 #define N 1100000
 7 using namespace std;
 8 int m,n,k;
 9 int a[120];
10 int b[120];
11 int pos[N];
12 int g1[N];
13 int g2[N];
14 int dis[N][2];
15 int w[1<<20];
16 int dp[1<<20];
17 void bfs()
18 {
19     memset(w,0x3f,sizeof(w));
20     a[0]=0;
21     for(int i=1;i<=n;++i)
22         if(g2[i])a[++a[0]]=i,pos[i]=a[0];
23     queue<int>q;
24     int al,g,y;
25     for(int i=1;i<=a[0];++i)
26     {
27         al=1;
28         q.push(a[i]);dis[a[i]][0]=dis[a[i]][1]=0;
29         while(al<a[0]&&q.size())
30         {
31             g=q.front();q.pop();
32             for(int j=1;j<=m;++j)
33             {
34                 if(g-b[j]>0&&dis[g-b[j]][0]<i){
35                     y=g-b[j];
36                     dis[y][0]=i;
37                     dis[y][1]=dis[g][1]+1;
38                     if(pos[y]&&y!=a[i])
39                         w[(1<<i-1)|(1<<pos[y]-1)]=dis[y][1];
40                     else
41                     q.push(y);
42                 }
43                 if(g+b[j]<=n&&dis[g+b[j]][0]<i){
44                     y=g+b[j];
45                     dis[y][0]=i;
46                     dis[y][1]=dis[g][1]+1;
47                     if(pos[y]&&y!=a[i])
48                         w[(1<<i-1)|(1<<pos[y]-1)]=dis[y][1];
49                     else
50                     q.push(y);
51                 }
52             }
53         }
54         while(q.size())q.pop();
55     }
56 }
57 void work()
58 {
59     memset(dp,0x3f,sizeof(dp));
60     const int maxn=1<<a[0];dp[maxn-1]=0;
61     reg int t1,t2;
62     for(int i=maxn-1;i;--i)
63         for(int j=i;j;j-=j&-j){
64             t1=j&-j;
65             for(int o=j-(j&-j);o;o-=o&-o){
66                 t2=o&-o;
67                 dp[i^t1^t2]=min(dp[i^t1^t2],dp[i]+w[t1|t2]);
68             }
69         }
70     if(dp[0]>5000000)dp[0]=-1;
71     cout<<dp[0]<<endl;
72 }
73 int main()
74 {
75     scanf("%d%d%d",&n,&k,&m);
76     for(int i=1;i<=k;++i)
77         scanf("%d",&a[i]),g1[a[i]]=1;
78     ++n;
79     for(int i=1;i<=m;++i)
80         scanf("%d",&b[i]);
81     for(int i=1;i<=n;++i)
82         g2[i]=g1[i]^g1[i-1];
83     bfs();
84     work();
85     return 0;
86 }

B. 回文子串

其实还是比较水的一道题,除了样例弱一点没啥

然后维护答案可以用分快or线段树or树状数组。

求回文串可以用$PAM or Manacher or hash$

再加一个对拍就A了。上面的可以没有,但对拍必须有

  1 #include<bits/stdc++.h>
  2 #define N 50050
  3 #define ull unsigned long long
  4 using namespace std;
  5 int bl[N];
  6 char s[N];
  7 int n,sq,m,K;
  8 ull po[N],hs[N],hs2[N];
  9 const ull P=131;
 10 inline void geths(int l,int r){
 11     hs[l-1]=hs[r+1]=hs2[l-1]=hs2[r+1]=0;
 12     for(int i=l;i<=r;++i)hs[i]=hs[i-1]*P+s[i];
 13     for(int i=r;i>=l;--i)hs2[i]=hs2[i+1]*P+s[i];
 14 }
 15 struct seg1{
 16     int tag[N<<2];
 17     inline void down(int g){
 18         tag[g<<1]=tag[g<<1|1]=tag[g];
 19         tag[g]=0;
 20     }
 21     inline void change(int g,int l,int r,int x,int y,int c){
 22         if(l>y||r<x)return;
 23         if(l>=x&&r<=y){tag[g]=c;return;}
 24         const int m=l+r>>1;
 25         if(tag[g])down(g);
 26         change(g<<1,l,m,x,y,c);change(g<<1|1,m+1,r,x,y,c);
 27     }
 28     inline void getstr(int g,int l,int r,int x,int y){
 29         if(l>y||r<x)return;
 30         if(l==r){if(tag[g])s[l]=tag[g];return;}
 31         const int m=l+r>>1;if(tag[g])down(g);
 32         getstr(g<<1,l,m,x,y);getstr(g<<1|1,m+1,r,x,y);
 33     }
 34 }str;
 35 struct seg2{
 36     int sum[N<<2],tag[N<<2];
 37     inline void upd(int g){
 38         sum[g]=sum[g<<1]+sum[g<<1|1];
 39     }
 40     inline void down(int g,int l,int m,int r){
 41         tag[g<<1]=tag[g<<1|1]=tag[g];
 42         if(tag[g]==1)sum[g<<1]=m-l+1,sum[g<<1|1]=r-m;
 43         else sum[g<<1]=sum[g<<1|1]=0;
 44         tag[g]=0;
 45     }
 46     inline void change(int g,int l,int r,int x,int y,int v){
 47         if(l>y||r<x)return;
 48         if(l>=x&&r<=y){
 49             sum[g]=v>0?r-l+1:0;
 50             tag[g]=v;
 51             return;
 52         }
 53         const int m=l+r>>1;
 54         if(tag[g])down(g,l,m,r);
 55         change(g<<1,l,m,x,y,v);change(g<<1|1,m+1,r,x,y,v);
 56         upd(g);
 57     }
 58     inline int ask(int g,int l,int r,int x,int y){
 59         if(l>y||r<x)return 0;
 60         if(l>=x&&r<=y)return sum[g];
 61         const int m=l+r>>1;
 62         if(tag[g])down(g,l,m,r);
 63         return ask(g<<1,l,m,x,y)+ask(g<<1|1,m+1,r,x,y);
 64     }
 65 }tr[52];
 66 inline void init(){
 67     geths(1,n);
 68     for(int len=2;len<=K;++len){
 69         for(int i=len,j;i<=n;++i){
 70             j=i-len+1;
 71             if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len])
 72                 tr[len].change(1,1,n,i,i,1);
 73         }
 74     }
 75 }
 76 inline void work1(int l,int r,int c){
 77     str.change(1,1,n,l,r,c);
 78     for(int len=2;len<=K;++len)
 79         tr[len].change(1,1,n,l+len-1,r,1);
 80     for(int len=2;len<=K;++len)
 81         tr[len].change(1,1,n,r+1,min(n,r+len-1),-1),
 82         tr[len].change(1,1,n,l,min(l+len-2,n),-1);
 83     int lm,rm;
 84
 85     lm=max(r-K+2,1);rm=min(r+K,n);
 86     str.getstr(1,1,n,lm,rm);
 87     geths(lm,rm);
 88 //    printf("lm:%d rm:%d\n",lm,rm);
 89     for(int len=2;len<=K;++len){
 90         for(int i=r+1,j;i<=rm;++i){
 91             j=i-len+1;
 92             if(j>r)break;
 93             if(j<=0)continue;
 94 //            puts("yes1");
 95             if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len])
 96                 tr[len].change(1,1,n,i,i,1);//,cout<<i<<" ri "<<len<<endl;
 97         }
 98     }
 99     lm=max(l-K,1);rm=min(l+K-1,n);
100     rm=min(rm,r);
101     str.getstr(1,1,n,lm,rm);
102     geths(lm,rm);
103 //    printf("lm:%d rm:%d\n",lm,rm);
104     for(int len=2;len<=K;++len){
105         for(int i=l,j;i<=rm;++i){
106             j=i-len+1;
107             if(j>=l)break;if(j<=0)continue;
108 //            puts("yes2");
109             if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len])
110                 tr[len].change(1,1,n,i,i,1);//,cout<<i<<" le "<<len<<endl;
111         }
112     }
113 //    cout<<tr[2].sum[1]<<" "<<tr[3].sum[1]<<endl;
114 }
115 inline int getans(int l,int r){
116     int ret=r-l+1;
117     for(int len=2;len<=K;++len)
118         ret+=tr[len].ask(1,1,n,l+len-1,r);
119     return ret;
120 }
121 int main(){
122     scanf("%s%d%d",s+1,&K,&m);
123     n=strlen(s+1);sq=sqrt(n)+1;
124     po[0]=1;for(int i=1;i<=n;++i)po[i]=po[i-1]*P;
125     init();
126     char S[3];
127     for(int i=1,op,x,y;i<=m;++i){
128 //        cout<<"i::"<<i<<endl;
129         scanf("%d",&op);
130         if(op==1){
131             scanf("%d%d%s",&x,&y,S);
132             work1(x,y,S[0]);
133         }
134         else{
135             scanf("%d%d",&x,&y);
136             printf("%d\n",getans(x,y));
137         }
138     }
139     return 0;
140 }

C. 最大价值

大神T3,%%%skyh考场切掉(然而没开long long 挂得还不如暴力xswl)

当所选序列确定以后,一定是按a从小到大放。

首先60分可以直接按a从小到大排序,然后大力dp。

然后满分可以康这位大神的博客

 1 #include<bits/stdc++.h>
 2 #define N 300050
 3 #define LL long long
 4 using namespace std;
 5 struct node{
 6     LL a,b;
 7     friend bool operator <(const node &x,const node &y){
 8         return x.a==y.a?x.b<y.b:x.a<y.a;
 9     }
10 }q[N];
11 struct Splay{
12     LL val[N],tag[N];
13     int fa[N],ch[N][2],sz[N],rt,tot;
14     inline int Get(int x){return ch[fa[x]][1]==x;}
15     inline void upd(int g){sz[g]=sz[ch[g][0]]+sz[ch[g][1]]+1;}
16     inline void rotate(int x){
17         int y=fa[x],z=fa[y],p=Get(x),w=ch[x][p^1];
18         if(w)fa[w]=y;ch[y][p]=w;
19         if(z)ch[z][Get(y)]=x;fa[x]=z;
20         fa[y]=x;ch[x][p^1]=y;
21         upd(y);upd(x);
22     }
23     inline void push1(int g,LL v){if(!g||!v)return;val[g]+=v;tag[g]+=v;}
24     inline void down(int x){push1(ch[x][0],tag[x]),push1(ch[x][1],tag[x]);tag[x]=0;}
25     inline void pushall(int x){if(!x)return;down(x);}
26     inline void splay(int x){while(fa[x])rotate(x);rt=x;}
27     inline void insert(int i){
28         ++tot;sz[tot]=1;
29         if(!rt){rt=tot;val[rt]=q[i].b;return;}
30         LL a=q[i].a,b=q[i].b;
31         int x=rt,rk=0;
32         while(1){
33             down(x);
34             if(a*(rk+sz[ch[x][0]])+b>val[x]){
35                 if(ch[x][0])x=ch[x][0];
36                 else{ch[x][0]=tot;fa[tot]=x;break;}
37             }
38             else{
39                 rk+=sz[ch[x][0]]+1;
40                 if(ch[x][1])x=ch[x][1];
41                 else{ch[x][1]=tot;fa[tot]=x;break;}
42             }
43         }
44         val[tot]=a*rk+b;
45         splay(tot);push1(ch[rt][1],a);
46     }
47     inline void bl(int g,LL &ans){
48         down(g);
49         if(ch[g][0])bl(ch[g][0],ans);
50         ans+=val[g];
51         printf("%lld\n",ans);
52         if(ch[g][1])bl(ch[g][1],ans);
53     }
54 }s;
55 namespace ae86{
56     const int bufl=1<<15;
57     char buf[bufl],*s=buf,*t=buf;
58     inline int fetch(){
59         if(s==t){t=(s=buf)+fread(buf,1,bufl,stdin);if(s==t)return EOF;}
60         return*s++;
61     }
62     inline LL read(){
63         LL a=0,b=1,c=fetch();
64         while(!isdigit(c))b^=c==‘-‘,c=fetch();
65         while(isdigit(c))a=a*10+c-48,c=fetch();
66         return b?a:-a;
67     }
68 }
69 using ae86::read;
70 int n;
71 int main(){
72     n=read();
73     for(int i=1;i<=n;++i)q[i].a=read(),q[i].b=read();
74     sort(q+1,q+n+1);LL ans=0;
75     for(int i=1;i<=n;++i)s.insert(i);
76     s.bl(s.rt,ans);
77     return 0;
78 }

原文地址:https://www.cnblogs.com/loadingkkk/p/12193429.html

时间: 2024-10-14 16:06:54

省选模拟6&7的相关文章

省选模拟(61~65)

省选模拟61 1.GTM \(BIT\) 把所有点按照下标排序后,考虑消灭一个点会给多少个点消灭掉 发现左边速度比它大的和右边速度比它小的都能够通过接触它消灭 继续分情况,考虑左边速度比它小的一些点 如果速度比右边速度的最小值要大的话就可以通过接触右边的点消灭 同理对于右边速度比它大的点只要比左边最大值小就照样可以消灭掉 所以每个点能够消灭的,是速度一段区间内的点\([min,max]\) 然后就是线段覆盖问题了 2.字符串游戏 ? 考虑已经知道答案是多少了,然后就是有一个\(ans*n\)的网

省选模拟(66~70)

省选模拟66 1.有限空间跳跃理论 \(FWT\) 给定一个无向图,要求给每条边定向后成为有向无环图,求方案 考虑那个\(dp\) \[dp[S]=\sum_{W\in S}(-1)^{|W|-1}dp[S-W] \] 发现就是一个子集卷积的形式,所以开第二维再卷积就好了 省选模拟67 1.链 模拟 发现如果度数都小于3就可以根据有无环出答案 否则假如第一个度数等于3的点为\(x\),那么为了使\(x\)最后度数小于3,最终消掉的点就只能是\(x\)或它相邻的3个点这四种选择 所以把去掉这4个点

2018.3.10 省选模拟赛

从这里开始 概况 Problem A 三元组 Problem B 攻略 Problem C 迂回 概况 这是省选T1合集?还是欢乐AK赛? 全班一半以上的人三道题都会做qwq. Doggu还剩一小时时以为自己AK了,然后玩了一小时.虽然最终被卡了20分的常数. ZJC 1个半小时AK?Excuse me? 我这条大咸鱼到最后10分钟才敲完了T1,然后发现线段树要T掉. 发自内心鄙视垃圾出题人卡常数,本来的欢乐AK变成280. 教练给我们考4个小时的试,题面上也这么写的,看题解,woc,考试时间3

[考试反思]0113省选模拟6:过载

真累啊...离上次放假也挺久,离下次放假也挺久,离上次放出去玩也挺久,离下次放出去玩还不知道有多久... 好累啊...大脑基本成天在挂机了.什么也不想干了... 持续状态不佳.但是今天运气好,所以考试排名看起来还可以. T1没认真读题也没看数据范围,以为是送分题,17分钟写完交了...然后我就把分送出去了 像个弱智一样...但是现在的精神状态的确不太能支持好好做题 幸亏T2是个比较简单的SAM+dp,思维量不大,脑子宕机的时候也能写一写. (归功于当时给大家讲课时稍微有一点理解,要是其它的板子我

[考试反思]0114省选模拟7:迷离

这次考得相对不错,但是没什么水准. 只不过记得T1这道原题而已.虽说我忘了怎么做,而且数据范围不一样...差不多是从头想的. 但是并没有AC,像个弱智一样,有两个细节写的完全不对还有80分运气也是真好. 其实挂了不止两个细节...以为是原题于是上来就写20分钟写完,然后过一会出一个锅... 然后看T2,感觉$O(nk^2)$也许差不多?常数很大...但也不会别的.挺好想但是不是很好写. 于是乎强烈谴责cbx没素质暴力水题考后还不改正解的无脸行径 于是就开始写,写了一个半小时. 看T3,绝对大神题

省选模拟二十九 题解

T1 考场上只想到了枚举拆三元环,拿到60pts 发现其实有一个性质没有用到: 保证将这  个点移除后,剩余的图将不存在环. 假设黑点为没有被钦定的点,白点反之 三白的情况无解 那么一个三元环只能由二黑一白/二白一黑组成, 后者已经固定了,直接选,而前者并不是很好处理 首先对黑白点分别求出子图的Top序(由于是竞赛图,所以Top序是严格的) 接着对于每个黑点处理出它到白点的一个序列(设W->B=1,B->W=0) 把序列按照白点Top序排序 考虑什么样的x才是不合法的 当且仅当存在一个0在1的

省选模拟三十四 题解

T1 假如max(a)<0的话直接把所有的a排个序贪心选择大的尽量多 现在考虑一个正的ai对后面的影响 维护一个大根堆,a<0就往里添,a>=0就去抵消堆顶元素 这样新序列(堆里的元素)就可以像刚才那样做了 T2 先把点按权值从大到小排序 然后枚举那个点可以选也可以不选 前面的都已经选了 然后在当前枚举的颜色中优先选择那些到根的路径上权值合法的 更新答案 因为如果要是想往小枚举的话一定要选择完当前颜色 所以把当且颜色全部连到根上后还需要额外的考虑中间小于当且权值的点 就是一个递归模拟 最

省选模拟五十六 题解

T1 异或和为0则先手必败 设\(dp[i][j][k]\)代表考虑到\(i\)选了\(j\)个数(对\(d\)取模)异或和为\(k\)的方案数 假如把\(a\)从大到小排序的话便可以剪枝: 第三维是\(2^b\)(b是满足\(2^b>a[i]\)的第一个数) 复杂度\(O(1e7*d)\) T2 设\(f[i][j][k]\)代表从S走k步到T不经过S,T的方案数 \(g[i][j][k]\)代表从S走k步到T的方案数 \(h[i][j][k]\)代表从S走k步到S不经过T的方案数 \(g\)

2018.2.12 省选模拟赛

题目大意 (题目很简洁了,不需要大意) 其实显而易见地可以发现,当被卡一次后后面的路程都是固定了的. 可以用类似动态规划的思想来进行预处理.现在的问题就是怎么知道在某个位置刚等完红灯然后出发会在哪个路口再次被卡. 尝试画一画图: 其中横轴表示位置,纵轴表示时间,长方体表示红灯时段.有用的部分长度只有$r + g$,所以在模意义下弄一下就可以减少很多重复和无用状态: 但是这样仍然不好处理上面提到的问题,考虑让线段横着走,第一个撞着的长方形就是答案.为了实现这个目标,就每个长方形向下移动一段(移动的

2018/3/1 省选模拟考试 50分

T1 30分模拟暴力,40分树的直径.拿了0分.(空间开小了爆了,因为缩点之后是又建了一次图,两个边的编号tot没分开,mdzz) 只写了后40分,而这40分中有20分不需要边双连通分量.写了一个类似于强连通分量(标记双向边)的缩点,应该实现哪里出了偏差,因为就算空间开大改正tot的bug也还是20分. T2 写了50分纯暴力 会bsgs可以得80分好像,但是我只会快速幂和暴力,所以50. T3 看了题目,没写,感觉是lca和一些神奇的操作.题解看上去是一个挺裸的lca,亏了. 原文地址:htt