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 }
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 }
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 }
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 }
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 }
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 }
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 }