Educational Codeforces Round 62 做题记录

A.

题解:

发现就是找前缀 max = i 的点的个数,暴力扫一遍

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pii pair<int,int>
 4 #define mp(a,b) make_pair(a,b)
 5 using namespace std;
 6 #define maxn 10005
 7 int n;
 8 int a[maxn];
 9 int main()
10 {
11     scanf("%d",&n);
12     for(int i=1;i<=n;++i)
13     {
14         scanf("%d",&a[i]);
15     }
16     int ans=0,last=0;
17     for(int i=1;i<=n;++i)
18     {
19         last=max(a[i],last);
20         if(i>=last)ans++;
21     }
22     printf("%d\n",ans);
23     return 0;
24 }
View Code

 

B.

题解:

找到最左边的>,删去其左边的<;

或找到最右边的<,删去其右边的>;

两种方法取最优

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pii pair<int,int>
 4 #define mp(a,b) make_pair(a,b)
 5 using namespace std;
 6 #define maxn 105
 7 int T,n;
 8 char s[maxn];
 9 int main()
10 {
11     scanf("%d",&T);
12     while(T--)
13     {
14         scanf("%d",&n);
15         scanf("%s",s+1);
16         int ans=n-1;
17         for(int i=1;i<=n;++i)if(s[i]=='>')ans=min(ans,i-1);
18         for(int i=n;i>=1;--i)if(s[i]=='<')ans=min(ans,n-i);
19         printf("%d\n",ans);
20     }
21     return 0;
22 }
View Code

 

C.

题解:

我们将元素按b排序,从大往小加入

显然当前b为最小,已经固定

考虑找前k大的t,用优先队列维护就行

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pii pair<int,int>
 4 #define mp(a,b) make_pair(a,b)
 5 using namespace std;
 6 #define maxn 300005
 7 int n,k;
 8 struct data
 9 {
10     ll t,b;
11 }a[maxn];
12 bool operator < (data A,data B)
13 {
14     return A.b>B.b;
15 }
16 priority_queue<ll,vector<ll>,greater<ll>> pq;
17 int main()
18 {
19     scanf("%d%d",&n,&k);
20     for(int i=1;i<=n;++i)scanf("%I64d%I64d",&a[i].t,&a[i].b);
21     sort(a+1,a+n+1);
22     int sz=0;
23     ll sum=0,ans=0;
24     for(int i=1;i<=n;++i)
25     {
26         if(sz<k)
27         {
28             sz++;
29             pq.push(a[i].t);sum+=a[i].t;
30             ans=max(ans,sum*a[i].b);
31         }
32         else
33         {
34             sum+=a[i].t; pq.push(a[i].t);
35             ll x=pq.top();pq.pop();
36             sum-=x;
37             ans=max(ans,sum*a[i].b);
38         }
39     }
40     printf("%I64d\n",ans);
41     return 0;
42 }
View Code

 

D.

题解:

观察发现,ans=2*3+3*4+4*5+……+(n-1)*n

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pii pair<int,int>
 4 #define mp(a,b) make_pair(a,b)
 5 using namespace std;
 6 int n;
 7 int main()
 8 {
 9     scanf("%d",&n);
10     ll ans=0;
11     for(int i=2;i<n;++i)
12     {
13         ans+=1ll*i*(i+1);
14     }
15     printf("%I64d\n",ans);
16     return 0;
17 }
View Code

 

E.

题解:

考虑题目给定的条件,不能出现奇数回文串等价于不能出现a[i]==a[i-2]的情况

按奇偶分类,取分类完的序列A,长度为len

等价于每个-1可以染k种颜色,不能出现相邻两个格子染色相同

如果A中没有已经确定的数,那么ans=k*(k-1)^(len-1)

如果A中有一个已经确定的数,那么ans=(k-1)^(len-1)

如果A中>=2个已确定的数,那么左右两端同上述情况,中间的就是一个经典的染色DP

f ( i , 0 )表示两端数字不同时,i和结尾不同的方案数

f ( i , 1 )表示两端数字不同时,i和结尾相同的方案数

g ( i , 0 )表示两端数字相同时,i和结尾不同的方案数

g ( i , 1 )表示两端数字相同时,i和结尾相同的方案数

 转移显然

细节和边界条件比较多,比赛时候写错一个小地方WA到死qwq

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define pii pair<int,int>
  4 #define mp(a,b) make_pair(a,b)
  5 using namespace std;
  6 #define maxn 200005
  7 const ll mod = 998244353;
  8 ll f[maxn][2],g[maxn][2];
  9 ll fastpow(ll a,ll p)
 10 {
 11     ll ans=1;
 12     while(p)
 13     {
 14         if(p&1)ans=ans*a%mod;
 15         a=a*a%mod;p>>=1; 
 16     }
 17     return ans;
 18 }
 19 ll work(ll *a,int n,ll k)
 20 {
 21     for(int i=2;i<=n;++i)if(a[i]==a[i-1]&&a[i]!=-1)return 0;
 22     int p=0;
 23     for(int i=1;i<=n;++i)if(a[i]!=-1)p++;
 24     if(!p)
 25     {
 26         return fastpow(k-1,n-1)*k%mod;
 27     }
 28     else if(p==1)
 29     {
 30         return fastpow(k-1,n-1);
 31     }
 32     else
 33     {
 34         if(p==n)return 1;
 35         if(k==1)return 0;
 36         ll res=1;
 37         int l,r;
 38         for(int i=1;i<=n;++i)
 39         {
 40             if(a[i]!=-1)
 41             {
 42                 l=i+1;
 43                 break;
 44             }
 45             res=res*(k-1)%mod;
 46         }
 47         for(int i=n;i;--i)
 48         {
 49             if(a[i]!=-1)
 50             {
 51                 r=i-1;
 52                 break;
 53             }
 54             res=res*(k-1)%mod;
 55         }
 56         ll t=0;
 57         ll last=a[l-1];
 58         for(int i=l;i<=r+1;++i)
 59         {
 60             if(a[i]!=-1)
 61             {
 62                 if(!t)
 63                 {
 64                     last=a[i];
 65                     continue;
 66                 }
 67                 if(a[i]!=last)res=(res*f[t][0])%mod;
 68                 else res=(res*g[t][0])%mod;
 69                 t=0;last=a[i];
 70             }
 71             else t++;
 72         }
 73         return res;
 74     }
 75 }
 76 int n,cnt1,cnt2;
 77 ll k;
 78 ll a[maxn],b[maxn],c[maxn];
 79 int main()
 80 {
 81     scanf("%d%I64d",&n,&k);
 82     for(int i=1;i<=n;++i)
 83     {
 84         scanf("%I64d",&a[i]);
 85     }
 86     f[1][0]=k-2;f[1][1]=1;
 87     g[1][0]=k-1;g[1][1]=0;
 88     for(int i=2;i<=n;++i)
 89     {
 90         f[i][0]=(f[i-1][0]*(k-2)%mod+f[i-1][1]*(k-1)%mod)%mod;
 91         f[i][1]=f[i-1][0];
 92         g[i][0]=(g[i-1][0]*(k-2)%mod+g[i-1][1]*(k-1)%mod)%mod;
 93         g[i][1]=g[i-1][0];
 94     }
 95     for(int i=1;i<=n;i+=2)b[++cnt1]=a[i];
 96     for(int i=2;i<=n;i+=2)c[++cnt2]=a[i];
 97     ll ans=work(b,cnt1,k);
 98     ans=ans*work(c,cnt2,k)%mod;
 99     printf("%I64d\n",ans);
100     return 0;
101 }
View Code

 

F.

题解:

考虑把横坐标看成点,纵坐标看成点,每次加入一对数相当于连边

然后R的大小就是连通块中横点个数*纵点个数

动态图连通性

离线下来分治线段树,用可撤销并查集维护

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define pii pair<int,int>
  4 #define mp(a,b) make_pair(a,b)
  5 #define maxn 600005
  6 using namespace std;
  7 int q,n=300000;
  8 struct Edg
  9 {
 10     int x,y;
 11 }a[maxn],b[maxn];
 12 int c[maxn],last[maxn];
 13 struct Option
 14 {
 15     int l,r,x,y;
 16 }opt[maxn];
 17 bool operator < (Edg A,Edg B)
 18 {
 19     if(A.x==B.x)return A.y<B.y;
 20     return A.x<B.x;
 21 }
 22 bool operator == (Edg A,Edg B)
 23 {
 24     return (A.x==B.x&&A.y==B.y);
 25 }
 26 int fa[maxn],sz1[maxn],sz2[maxn],size[maxn];
 27 int find(int x)
 28 {
 29     while(fa[x]!=x)x=fa[x];
 30     return x;
 31 }
 32 vector<pii> ve[maxn<<2];
 33 void add(int rt,int l,int r,int ql,int qr,pii x)
 34 {
 35     if(ql<=l&&r<=qr)
 36     {
 37         ve[rt].push_back(x);
 38         return;
 39     }
 40     int mid=(l+r)>>1;
 41     if(ql<=mid)add(rt<<1,l,mid,ql,qr,x);
 42     if(qr>mid)add(rt<<1|1,mid+1,r,ql,qr,x);
 43 }
 44 int s1[maxn],s2[maxn],top;
 45 ll Ans[maxn],res=0;
 46 void dfs(int rt,int l,int r)
 47 {
 48     if(l>r)return;
 49     int bot=top;
 50     for(int i=0;i<ve[rt].size();++i)
 51     {
 52         int u=ve[rt][i].first,v=ve[rt][i].second;
 53         if(find(u)==find(v))continue;
 54         u=find(u),v=find(v);
 55         if(size[u]<size[v])swap(u,v);
 56         res-=1ll*sz1[u]*sz2[u]+1ll*sz1[v]*sz2[v];
 57         fa[v]=u;
 58         size[u]+=size[v];sz1[u]+=sz1[v],sz2[u]+=sz2[v];
 59         s1[++top]=v;s2[top]=u;
 60         res+=1ll*sz1[u]*sz2[u];
 61     }
 62     if(l==r)
 63     {
 64         Ans[l]=res;
 65     }
 66     int mid=(l+r)>>1;
 67     if(l!=r)
 68     {
 69         dfs(rt<<1,l,mid);
 70         dfs(rt<<1|1,mid+1,r);
 71     }
 72     while(top>bot)
 73     {
 74         int u=s1[top],v=s2[top];
 75         res-=1ll*sz1[v]*sz2[v];
 76         fa[u]=u;
 77         size[v]-=size[u];sz1[v]-=sz1[u];sz2[v]-=sz2[u];
 78         res+=1ll*sz1[u]*sz2[u]+1ll*sz1[v]*sz2[v];
 79         top--;
 80     }
 81 }
 82 int main()
 83 {
 84     scanf("%d",&q);
 85     for(int i=1;i<=q;++i)
 86     {
 87         scanf("%d%d",&a[i].x,&a[i].y);
 88         a[i].y+=n;
 89         b[i]=a[i];
 90     }
 91     sort(a+1,a+q+1);
 92     int d=unique(a+1,a+q+1)-a-1;
 93     for(int i=1;i<=q;++i)c[i]=lower_bound(a+1,a+d+1,b[i])-a;
 94     int cnt=0;
 95     for(int i=1;i<=q;++i)
 96     {
 97         if(!last[c[i]])last[c[i]]=i;
 98         else
 99         {
100             ++cnt;
101             opt[cnt].l=last[c[i]],opt[cnt].r=i-1,opt[cnt].x=a[c[i]].x,opt[cnt].y=a[c[i]].y;
102             last[c[i]]=0;
103         }
104     }
105     for(int i=1;i<=d;++i)if(last[i])
106     {
107         ++cnt;
108         opt[cnt].l=last[i],opt[cnt].r=q,opt[cnt].x=a[i].x,opt[cnt].y=a[i].y;
109         last[i]=0;
110     }
111     for(int i=1;i<=cnt;++i)add(1,1,q,opt[i].l,opt[i].r,mp(opt[i].x,opt[i].y));
112     for(int i=1;i<=n;++i)fa[i]=i,sz1[i]=1,size[i]=1;
113     for(int i=1;i<=n;++i)fa[i+n]=i+n,sz2[i+n]=1,size[i+n]=1;
114     dfs(1,1,q);
115     for(int i=1;i<=q;++i)printf("%I64d ",Ans[i]);
116     return 0;
117 }
View Code

 

G.

题解:

类似于ZJOI的某道题,多次询问两点最短路

一样的思路,分治最短路

分治改成树分治就好了

(这F和G怎么都是胖题)

  1 #include<bits/stdc++.h>
  2 #define ll long long
  3 #define maxn 600005
  4 using namespace std;
  5 int n,q;
  6 vector<int> T[maxn];
  7 int root;
  8 namespace Tree
  9 {
 10     struct edge
 11     {
 12         int to,next;
 13     }e[maxn<<1];
 14     int head[maxn],p;
 15     int cnt;
 16     void addedge(int u,int v)
 17     {
 18         e[++p].to=v;e[p].next=head[u];head[u]=p;
 19         e[++p].to=u;e[p].next=head[v];head[v]=p;
 20     }
 21     int rt,nowsize;
 22     bool del[maxn];
 23     int sum[maxn],f[maxn];
 24     void getroot(int u,int fa)
 25     {
 26         sum[u]=1;f[u]=0;
 27         for(int i=head[u];i;i=e[i].next)
 28         {
 29             int v=e[i].to;
 30             if(v==fa||del[v])continue;
 31             getroot(v,u);
 32             sum[u]+=sum[v];
 33             if(sum[v]>f[u])f[u]=sum[v];
 34         }
 35         f[u]=max(f[u],nowsize-sum[u]);
 36         if(f[u]<f[rt])rt=u;
 37     }
 38     void solve(int u)
 39     {
 40         del[u]=1;
 41         for(int i=head[u];i;i=e[i].next)
 42         {
 43             int v=e[i].to;
 44             if(del[v])continue;
 45             rt=0;
 46             f[rt]=nowsize=sum[v];
 47             getroot(v,0);
 48             T[u].push_back(rt);
 49             T[u+1].push_back(rt+1); 
 50             solve(rt);
 51         }
 52     }
 53     void work()
 54     {
 55         rt=0;
 56         f[rt]=nowsize=n;
 57         getroot(1,0);
 58         root=rt;
 59         solve(rt);
 60     }
 61 };
 62 namespace Graph
 63 {
 64     const ll inf = (ll)2e18;
 65     struct Query
 66     {
 67         int u,v,id;
 68         Query(){}
 69         Query(int U,int V,int ID){u=U;v=V;id=ID;}
 70     };
 71     ll Ans[maxn];
 72     vector<Query> vq[maxn];
 73     struct edge
 74     {
 75         int to,next;
 76         ll w;
 77     }e[maxn<<2];
 78     bool used[maxn];
 79     bool del[maxn];
 80     int head[maxn],p;
 81     void addedge(int u,int v,ll w)
 82     {
 83         e[++p].to=v;e[p].w=w;e[p].next=head[u];head[u]=p;
 84         e[++p].to=u;e[p].w=w;e[p].next=head[v];head[v]=p;
 85     }
 86     struct node
 87     {
 88         int x;ll dis;
 89         node(){}
 90         node(int id,ll d){x=id;dis=d;}
 91     };
 92     bool operator < (node a,node b)
 93     {
 94         return a.dis>b.dis;
 95     }
 96     ll dis[maxn];
 97     void dijkstra(int s)
 98     {
 99         priority_queue<node> q;
100         q.push(node(s,0));dis[s]=0;
101         while(!q.empty())
102         {
103             int u=q.top().x;q.pop();
104             if(used[u])continue;
105             used[u]=1;
106             for(int i=head[u];i;i=e[i].next)if(!del[e[i].to])
107             {
108                 int v=e[i].to;
109                 ll w=e[i].w;
110                 if(dis[v]>dis[u]+w)
111                 {
112                     dis[v]=dis[u]+w;
113                     q.push(node(v,dis[v]));
114                 }
115             }
116         }
117     }
118     int belong[maxn];
119     void clear(int u)
120     {
121         dis[u]=inf;used[u]=0;
122         for(int i=0;i<T[u].size();++i)clear(T[u][i]);
123     }
124     void get_belong(int u,int rt,int tp)
125     {
126         belong[u]=rt+tp;
127         for(int i=0;i<T[u].size();++i)
128         {
129             int v=T[u][i];
130             get_belong(v,rt,tp);
131         }
132     }
133     void dfs(int rt)
134     {
135         if(!vq[rt].size())return;
136         clear(rt);
137         clear(rt+1);
138         dijkstra(rt);
139         for(int i=0;i<vq[rt].size();++i)
140         {
141             int u=vq[rt][i].u,v=vq[rt][i].v;
142             Ans[vq[rt][i].id]=min(Ans[vq[rt][i].id],dis[u]+dis[v]);
143         }
144         clear(rt);
145         clear(rt+1);
146         dijkstra(rt+1);
147         for(int i=0;i<vq[rt].size();++i)
148         {
149             int u=vq[rt][i].u,v=vq[rt][i].v;
150             Ans[vq[rt][i].id]=min(Ans[vq[rt][i].id],dis[u]+dis[v]);
151         }
152         del[rt]=1;del[rt+1]=1;
153         for(int i=0;i<T[rt].size();++i)get_belong(T[rt][i],T[rt][i],0);
154         for(int i=0;i<T[rt+1].size();++i)get_belong(T[rt+1][i],T[rt+1][i],-1);
155         for(int i=0;i<vq[rt].size();++i)
156         {
157             int u=vq[rt][i].u,v=vq[rt][i].v;
158             if(u==rt||v==rt||u==rt+1||v==rt+1)continue;
159             if(belong[u]==belong[v])vq[belong[u]].push_back(vq[rt][i]);
160         }
161         for(int i=0;i<T[rt].size();++i)dfs(T[rt][i]);
162     }
163     void work()
164     {
165         Tree::work();
166         for(int i=1;i<=q;++i)
167         {
168             int u,v;
169             scanf("%d%d",&u,&v);
170             vq[root].push_back(Query(u,v,i));
171             Ans[i]=inf;
172         }
173         dfs(root);
174         for(int i=1;i<=q;++i)printf("%I64d\n",Ans[i]);
175     }
176 }
177 int main()
178 {
179     scanf("%d",&n);
180     for(int i=1;i<=n;++i)
181     {
182         ll w;
183         scanf("%I64d",&w);
184         Graph::addedge(i*2-1,i*2,w);
185     }
186     for(int i=1;i<n;++i)
187     {
188         int x,y;ll w1,w2;
189         scanf("%d%d%I64d%I64d",&x,&y,&w1,&w2);
190         Graph::addedge(x*2-1,y*2-1,w1);
191         Graph::addedge(x*2,y*2,w2);
192         Tree::addedge(x*2-1,y*2-1);
193     }
194     scanf("%d",&q); 
195     Graph::work();
196     return 0;
197 }
View Code

 

posted @ 2019-03-23 19:34  幽蝶  阅读(329)  评论(0编辑  收藏  举报