Codeforces Round #790 (Div. 4)(已补完)
补题:F、G、H
Problem - F - Codeforces
tags
去重,最长序列,map的使用
问题
在找最长连续差1序列时超时了
代码实现部分太差了,多加练习和看别人代码
代码
超时代码
#include <bits/stdc++.h>
#include <set>
#include <vector>
#define ll long long
using namespace std;
int main()
{
int t;
for (cin >> t; t; t--)
{
int n, k;
cin >> n >> k;
multiset<int> s;
set<int> x;
for (int i = 0; i < n; i++)
{
int a;
cin >> a;
s.insert(a);
if (s.count(a) >= k && x.count(a) == 0)
{
x.insert(a);
}
}
if (x.size() == 0)
{
cout << -1 << endl;
continue;
}
int mx = -1, l = 0, r = 0;
for (auto it = x.begin(); it != x.end(); it++)
{
int h = *it;
while (x.count(++h));
h--;
if (h - *it > mx)
{
l = *it;
r = h;
mx = h - *it;
}
}
cout << l << ' ' << r << endl;
}
}
AC代码1
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
for(cin>>t;t;t--){
int n,k;
cin>>n>>k;
vector<int>num;
map<int,int>cnt;
for(int i=0;i<n;i++){
int x;cin>>x;
num.push_back(x);
cnt[x]++;
}
sort(num.begin(),num.end());
num.erase(unique(num.begin(),num.end()),num.end());//去重
int ans=-1,l=0,r=0;
for(int i=0;i<num.size();){
if(cnt[num[i]]<k){
i++;
continue;
}
int j=i+1;
while(j<num.size()&&cnt[num[j]]>=k&&num[j]-num[j-1]==1)j++;
if(num[j-1]-num[i]>ans)ans=num[j-1]-num[i],l=num[i],r=num[j-1];
i=j;//此次
}
if(ans==-1)cout<<-1<<endl;
else cout<<l<<' '<<r<<endl;
}
}
分析:
思路和我差不多
去重:sort+erase+unique
防止超时:在重新更新差为1的序列时,把i更新到序列最后去
但是我用的set<int>iterator it
无法去像这样用i操作
AC代码2
#include<iostream>
#include<map>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
for(cin>>t;t;t--){
int n,k;
cin>>n>>k;
map<int,int>m;
int mx=0;
for(int i=0;i<n;i++){
int x;cin>>x;
m[x]++;
mx=max(m[x],mx);
}
if(mx<k){
cout<<"-1\n";
continue;
}
int l=0,r=-1,ans=-1,el=0,er=0;
for(auto it=m.begin();it!=m.end();it++){
if(it->second<k)continue;
int x=it->first;
if(x-r!=1)l=x;
r=x;
if(r-l>ans){
ans=r-l;
el=l;
er=r;
}
}
cout<<el<<' '<<er<<endl;
}
}
分析:
直接用一个map实现计数,去重的操作
用迭代器遍历map
记录下上一个序列的r,若x-r==1,则可以继续更新序列,否则l=x开始新的序列
注意r初始化为-1,不然当有map里有1时无法记录去
Problem - G - Codeforces
tags
树,dfs
思路
- 从根节点开始,递推到叶子节点,期间记录下每个节点所有儿子的黑白总数
- 从叶子节点往回递归,返回黑白数给父亲
- 黑白可以用1、-1代替,因为黑白数相等时才平衡,所以d=0时为平衡
可以通过dfs实现,而用vector或链式前向星存树
代码
链式前向星
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=4*4005;
int n;
char str[maxn];
int head[maxn],cnt,ans;
struct Edge{
int u,v,next;
}edge[maxn];
void init(){
memset(head,-1,sizeof(head));
cnt=ans=0;
for(int i=0;i<maxn;i++)edge[i].u=edge[i].v=edge[i].next=0;
}
void add_edge(int u,int v){
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int dfs(int st){
int d=((str[st]=='W')?1:-1);
for(int i=head[st];i!=-1;i=edge[i].next)d+=dfs(edge[i].v);
if(d==0)ans++;
return d;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
for(cin>>t;t;t--){
init();
cin>>n;
for(int i=2;i<=n;i++){
int x;
cin>>x;
add_edge(x,i);
}
cin>>str+1;
dfs(1);
cout<<ans<<endl;
}
}
注意每一次测试样例要情况edge和ans和初始化head、cnt
vector
#include<iostream>
#include<vector>
using namespace std;
const int maxn=4*4005;
int n;
char str[maxn];
int count;
vector<int>g[maxn];
int dfs(int st){
int d=(str[st]=='W')?1:-1;
for(int i=0;i<g[st].size();i++)d+=dfs(g[st][i]);
if(d==0)count++;
return d;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
for(cin>>t;t;t--){
count=0;
for(int i=0;i<maxn;i++)g[i].clear();
cin>>n;
for(int i=2;i<=n;i++){
int x;cin>>x;
g[x].push_back(i);
}
cin>>str+1;
dfs(1);
cout<<count<<endl;
}
}
Problem - H2 - Codeforces
tags
归并排序
思路
- 由于n太大,不能按照简单版本去枚举 i < j 且 a [ i ] > = a [ j ] i<j且a[i]>=a[j] i<j且a[i]>=a[j]的情况
- 但找 i < j 且 a [ i ] > = a [ j ] i<j且a[i]>=a[j] i<j且a[i]>=a[j]的思路是不变的,而寻找它可以在归并排序的过程中枚举出来
- 归并排序复杂度为 O ( n l o n g n ) O(nlongn) O(nlongn),可以通过
其实归并排序的核心思想还是折半枚举
代码
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int n,a[maxn];
ll ans=0;
void merge(int l,int r){
if(l>=r)return;
vector<int>v;
int mid=(l+r)>>1;
merge(l,mid);
merge(mid+1,r);
int indexl=l,indexr=mid+1;
while(indexl<=mid&&indexr<=r){//这部分while另一种写法如下
if(a[indexl]>=a[indexr]){
v.push_back(a[indexr++]);
ans+=mid-indexl+1;
}
else v.push_back(a[indexl++]);
}
while(indexl<=mid)v.push_back(a[indexl++]);
while(indexr<=r)v.push_back(a[indexr++]);
for(int i=0;i<v.size();i++)a[i+l]=v[i];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
for(cin>>t;t;t--){
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
ans=0;
merge(0,n-1);
cout<<ans<<endl;
}
}
//上述while部分的另一种写法
while(indexl<=mid||indexr<=r){
if(indexl==mid+1)v.push_back(a[indexr++]);
else if(indexr==r+1)v.push_back(a[indexl++]);
else {
if(a[indexl]>=a[indexr]){
v.push_back(a[indexr++]);
ans+=mid-indexl+1;
}
else v.push_back(a[indexl++]);
}
}