Codeforces Round #558 (Div. 2)
A:
思路:m个人离开后,还剩n-m个人,枚举1~(n-m),看补上m个人是否能连成环
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e3+9; priority_queue<int>q; int main(){ int i,j,k,n,m; cin>>n>>m; if(n==m){ cout<<0<<endl; } else{ n-=m; for(i=n;i>=0;i--){ if(m>=i||i==1){ cout<<i<<endl; break; } } }B1
思路:判断前1~i这段序列是否合法,取最大值,注意到若序列合法,则删去一天之后,不同颜色出现的次数全部一样,即最多只能有一个颜色出现的次数不一样,并且这个颜色出现的次数必须刚好比其他颜色出现的次数多1或这个颜色出现的次数就是1.对B1的数据范围,我们完全可以纯暴力,枚举每个颜色,若这个颜色出现的次数减一之后所有颜色出现的次数都一样(特判一些颜色出现次数减一等于0的情况)
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+9; int a[maxn],mp[maxn]; int cnt[maxn]; set<int>st,st2; int main(){ ios::sync_with_stdio(0); cin.tie(0); int i,j,k,n,m; cin>>n; int ans=1; for(i=1;i<=n;i++){ cin>>a[i]; mp[a[i]]++; st.insert(a[i]); for(auto it:st){ mp[it]--; int flag=0; int x=it; int u; for(auto iter:st){ if(mp[iter]!=0)u=mp[iter]; } for(auto iter:st){ if(mp[iter]==0||mp[iter]==u){ continue; } else{ flag=1; break; } } mp[it]++; if(!flag){ ans=i; break; } } } cout<<ans<<endl; }B2:
思路:相比较B1,B2的颜色数据范围变大了,我们显然不能通过枚举颜色来解决问题。我们可以考虑声明一个set容器,维护颜色出现的次数,然后再开一个cnt数组储存这个序列颜色出现x次的有多少个颜色,每次将颜色出现次数插入到set容器的时候,对于我的这个程序而言,插入一u[i]颜色出现的次数时,需要撤销上次遍历到这个颜色时出现的次数的插入。处理完之后,只有当set的大小为2或为1时才可能合法,大小为2时,要么出现次数大的那个只有一个颜色出现过这么多次,并且次数只比其余颜色出现次数多1,要么次数小的那个颜色出现次数为1并且只有一个颜色出现过这么多次。大小为1时,只有出现次数这么多的颜色唯一或有多个颜色出现次数等于1时合法,有点绕
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+9; int a[maxn],mp[maxn]; int cnt[maxn]; set<int>st,ap_cnt; int main(){ ios::sync_with_stdio(0); cin.tie(0); int i,j,k,n,m; cin>>n; int ans=1; for(i=1;i<=n;i++){ cin>>a[i]; mp[a[i]]++; // st.insert(a[i]); cnt[mp[a[i]]]++; if(cnt[mp[a[i]]-1]!=0) cnt[mp[a[i]]-1]--; ap_cnt.insert(mp[a[i]]); if(cnt[mp[a[i]]-1]==0) ap_cnt.erase(mp[a[i]]-1); if(ap_cnt.size()==2){ int x=*ap_cnt.begin(),y=*++ap_cnt.begin(); // cout<<y<<' '<<cnt[y]<<endl; if(y-x==1&&(cnt[y]==1)||((cnt[x]==1&&x==1)))ans=i; } else if(ap_cnt.size()==1){ int x=*ap_cnt.begin(); if(x==1||cnt[x]==1)ans=i; } } cout<<ans<<endl; }C1:
思路:思路很简单,找出所有的不一样的直线,根据斜率判断是否相交,相交答案+1,去重感觉有点麻烦
代码:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f const int maxn=59; struct node{ int x,y,c; }a[maxn]; vector<node>line; map<tuple<int, int, int>,int>mp; int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } int main(){ int i,j,k,n; cin>>n; for(i=0;i<n;i++){ cin>>a[i].x>>a[i].y; } for(i=0;i<n;i++){ for(j=i+1;j<n;j++){ int x1=a[i].x,x2=a[j].x; int y1=a[i].y,y2=a[j].y; int c=x2*y1-x1*y2; /*if(x1-x2==0){ if(!mp[{(x1-x2),(y2-y1),c}]){ line.push_back({(x1-x2),(y2-y1),c}); mp[{(x1-x2),(y2-y1),c}]=1; continue; } } else if(y2-y1==0){ if(!mp[{(x1-x2),(y2-y1),c}]){ line.push_back({(x1-x2),(y2-y1),c}); mp[{(x1-x2),(y2-y1),c}]=1; continue; } }*/ int d=gcd((x1-x2),(y2-y1)); int t2=(x1-x2)/d,t1=(y1-y2)/d; c=t1*x1-t2*y1; if(!mp[tie(t1,t2,c)]){ line.push_back({t1,t2,c}); mp[tie(t1,t2,c)]=1; } } } int len=line.size(),ans=0; // cout<<len<<endl; for(i=0;i<len;i++){ // cout<<line[i].x<<' '<<line[i].y<<' '<<line[i].c<<endl; for(j=i+1;j<len;j++){ if(line[i].x==line[j].x&&line[i].y==line[j].y){ continue; } ans++; } } cout<<ans<<endl; }C2:
思路:这道题最多有1e6条边,不能暴力判断两条边是否相交了,我们可以找出每一个斜率的边数(截距不同)x,然后用(总的边数-x*)x,因为每一个斜率我们会重复计算一次,所以最后的答案我们要除以二。啊,感觉我的代码写的跟屎一样。
代码:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f const int maxn=1e3+9; struct node{ int x,y,c; }a[maxn]; vector<node>line; map<tuple<int, int, int>,int>mp; map<pair<int,int>,int>mmp; int cnt[maxn]; int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } set<int>st; int main(){ ios::sync_with_stdio(0); cin.tie(0); int i,j,k,n; cin>>n; for(i=0;i<n;i++){ cin>>a[i].x>>a[i].y; } for(i=0;i<n;i++){ for(j=i+1;j<n;j++){ int x1=a[i].x,x2=a[j].x; int y1=a[i].y,y2=a[j].y; int c=x2*y1-x1*y2; int d=gcd((x1-x2),(y2-y1)); int t2=(x1-x2)/d,t1=(y1-y2)/d; c=t1*x1-t2*y1; if(!mp[tie(t1,t2,c)]){ mmp[{t1,t2}]++; cnt[mmp[{t1,t2}]]++; if(cnt[mmp[{t1,t2}]-1]!=0){ cnt[mmp[{t1,t2}]-1]--; } st.insert(mmp[{t1,t2}]); if(cnt[mmp[{t1,t2}]-1]==0){ st.erase(mmp[{t1,t2}]-1); } line.push_back({t1,t2,c}); mp[tie(t1,t2,c)]=1; } } } long long len=line.size(),ans=0; for(auto it:st){ //cout<<it<<endl; ans+=cnt[it]*it*(len-it*); } cout<<ans/2<<endl; }