万里无云,又是平静的一天。


3843. 寻找羔羊(agnus) (Standard IO)

Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits  
Goto ProblemSet
 
 
 

On遍历串,找到s就判一下是否形成agnus,如果形成就统计(乘法原理)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char c[30010];
 4 bool isagnus(int i){
 5     return (c[i-4]=='a'&&c[i-3]=='g'&&c[i-2]=='n'&&c[i-1]=='u');
 6 }
 7 int nxt;
 8 long long ans;
 9 int main(){
10     cin>>c;
11     nxt=-1;
12     int len=strlen(c);
13     for(int i=0;i<len;i++){
14         if(c[i]=='s'){
15             if(isagnus(i)){
16                 ans+=(i-4-nxt)*(len-i);
17                 nxt=i-4;
18             }
19         }
20     }
21     printf("%d",ans);
22     return 0;
23 }

3844. 统计损失(count) (Standard IO)

Time Limits: 1000 ms  Memory Limits: 524288 KB  Detailed Limits  
Goto ProblemSet
 
 
 

考虑dp,用f[i][0/1]分别表示从以i为根节点的子树中,经过点i而是否上去的路径答案。

发现处理f[i][0]时复杂度似乎太高,考虑优化:

用v表示f[v][1]:

 这样就能在线维护了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 typedef long long ll;
17 const int N=1e5+10;
18 const int p=10086;
19 ll val[N];
20 ll f[N][2];
21 int n;
22 struct edge{ int to,nxt; }e[N<<1];
23 int head[N<<1],cnt;
24 void addedge(int from,int to){e[++cnt]=(edge){to,head[from]};head[from]=cnt;}
25 void dfs(int u,int fa){
26     f[u][1]=(val[u])%p;
27     ll tot=0,sum=0;
28     for(int i=head[u];i;i=e[i].nxt){
29         int v=e[i].to;
30         if(v==fa) continue;
31         dfs(v,u);
32         tot=f[v][1];
33         f[u][0]=(f[u][0]+tot*sum*val[u])%p;
34         sum=(sum+tot)%p;
35         f[u][1]=(f[u][1]+f[v][1]*val[u])%p;
36     }
37 }
38 int main(){
39     n=read();
40     for(int i=1;i<=n;i++) val[i]=read();
41     for(int i=1,x,y;i<n;i++){
42         x=read(),y=read();
43         addedge(x,y);
44         addedge(y,x);
45     }
46     dfs(1,0);
47     ll ans=0;
48     for(int i=1;i<=n;i++){
49         ans=(ans+f[i][0]+f[i][1])%p;
50     }
51     printf("%lld",ans);
52     return 0;
53 }

3845. 简单题(simple) (Standard IO)

Time Limits: 1000 ms  Memory Limits: 524288 KB  Detailed Limits  
Goto ProblemSet
 
 
 

分析题。

发现如果存在一个图满足条件,那么它一定是一条编号连续的链,用一些边将其中的点连接。

又发现这道题不用图论,直接dp即可(找的就是不相交线段条数)。

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(3)
 3 using namespace std;
 4 int read(){
 5     int x=0,f=1;
 6     char c=getchar();
 7     while(!isdigit(c)){
 8         if(c=='-') f=-1;
 9         c=getchar();
10     }
11     while(isdigit(c)){
12         x=(x<<1)+(x<<3)+(c^48);
13         c=getchar();
14     }
15     return x*f;
16 }
17 const int N=2e5+10;
18 int n,m;
19 int f[N];
20 int l[N];
21 int main(){
22     n=read();m=read();
23     for(register int i=1;i<=m;i++){
24         int ll=read(),rr=read();
25         if(ll>rr) swap(ll,rr);
26         if(ll<rr-1){
27             l[rr]=max(l[rr],ll);
28         }
29     }
30     for(register int i=1;i<=n;i++){
31         if(l[i]) f[i]=max(f[i-1],f[l[i]]+1);
32         else f[i]=f[i-1];
33     }
34     printf("%d",f[n]+n-1);
35     return 0;
36 }
12-29 14:26
查看更多