比賽總結
算了不提了,比賽時只弄出來第一題,wa了7次,罰時跪得一塌糊塗,*了狗了。。。
A. Removing Columns
題目鏈接
http://codeforces.com/contest/497/problem/A
題目大意
給你
思路
非常坑爹的細節題,其間不知道wa了多少次。。。。
顯然是個貪心,我們從第一列到最後一列掃,只要能保留的列,保留下來肯定對後面沒有影響。
如果當前在保留下來的列中,某些字符串的前綴都一樣:
AAAAAA?…..
AAAAAA?…..
…….
AAAAAA?…..
那麼?列就必須得按照字母非降排序,類似下面這樣
AAAAAA A…..
AAAAAA B…..
…….
AAAAAA E…..
否則這一列隨便什麼順序都行
我們可以維護一個數組
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 510
using namespace std;
char mp[MAXN][MAXN];
int n,m,maxans=0;
bool mark[MAXN];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
int ans=0;
for(int j=1;j<=m;j++)
{
bool flag=true;
for(int i=1;i<n;i++)
{
if(!mark[i]&&mp[i][j]>mp[i+1][j])
{
ans++;
flag=false;
break;
}
}
if(flag)
{
for(int i=1;i<n;i++)
if(mp[i][j]<mp[i+1][j])
mark[i]=true;
}
}
printf("%d\n",ans);
return 0;
}
B. Tennis Game
題目鏈接
http://codeforces.com/contest/497/problem/B
題目大意
A和B打
思路
首先我們枚舉
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define MAXN 210000
using namespace std;
int n;
int result[MAXN];
int sumA[MAXN],sumB[MAXN];
vector<pair<int,int> >sol;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&result[i]);
for(int i=1;i<=n;i++)
{
sumA[i]=sumA[i-1]+(result[i]==1);
sumB[i]=sumB[i-1]+(result[i]==2);
}
for(int t=1;t<=n;t++)
{
int totA=0,totB=0,p=0;
while(p<n)
{
int lowerBound=p+1,upperBound=n,ans=-1;
while(lowerBound<=upperBound)
{
int mid=(lowerBound+upperBound)>>1;
if(sumA[mid]-sumA[p]>=t||sumB[mid]-sumB[p]>=t)
{
ans=mid;
upperBound=mid-1;
}
else lowerBound=mid+1;
}
if(ans==-1) break;
if(sumA[ans]-sumA[p]>=t&&sumB[ans]-sumB[p]<t) totA++;
if(sumA[ans]-sumA[p]<t&&sumB[ans]-sumB[p]>=t) totB++;
if(ans==n&&totA!=totB)
{
if(totA>totB&&result[ans]!=1) break;
if(totA<totB&&result[ans]!=2) break;
sol.push_back(make_pair(max(totA,totB),t));
}
p=ans;
}
}
sort(sol.begin(),sol.end());
printf("%d\n",sol.size());
for(int i=0;i<sol.size();i++)
printf("%d %d\n",sol[i].first,sol[i].second);
return 0;
}
C. Distributing Parts
題目鏈接
http://codeforces.com/contest/497/problem/C
題目大意
給你
思路
比較簡單的貪心。我們首先將紅色線段和藍色線段按照第一關鍵字右端點升序、第二關鍵字左端點升序來排序,然後從左到右掃藍色線段
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
#define MAXN 210000
using namespace std;
int n,m;
struct Segment
{
int L,R,k,id;
}song[MAXN],musician[MAXN];
bool operator<(Segment a,Segment b)
{
if(a.R==b.R)
return a.L<b.L;
return a.R<b.R;
}
int belong[MAXN];
struct Info
{
int L,R,id;
Info(){}
Info(int _L,int _R,int _id):L(_L),R(_R),id(_id){}
};
bool operator<(Info a,Info b)
{
if(a.L==b.L) return a.R<b.R;
return a.L<b.L;
}
bool operator>(Info a,Info b)
{
if(a.L==b.L)
return a.R>b.R;
return a.L>b.L;
}
multiset<Info>bst; //!!!
multiset<Info>::iterator it;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&song[i].L,&song[i].R);
song[i].id=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&musician[i].L,&musician[i].R,&musician[i].k);
musician[i].id=i;
}
sort(song+1,song+n+1);
sort(musician+1,musician+m+1);
int p=1,tot=0; //tot=被演奏的歌曲個數
for(int i=1;i<=m;i++)
{
for(;p<=n&&song[p].R<=musician[i].R;p++)
{
//cout<<"L:"<<song[p].L<<" R:"<<song[p].R<<endl;
bst.insert(Info(song[p].L,song[p].R,song[p].id));
}
for(int t=1;t<=musician[i].k;t++)
{
it=bst.lower_bound(Info(musician[i].L,0,0));
if(it==bst.end()) break;
belong[it->id]=musician[i].id;
bst.erase(it);
tot++;
}
}
if(tot!=n)
{
printf("NO\n");
return 0;
}
printf("YES\n");
for(int i=1;i<=n;i++)
printf("%d ",belong[i]);
printf("\n");
return 0;
}
D. Gears
題目鏈接
http://codeforces.com/contest/497/problem/D
題目大意
給你兩個多邊形,每個多邊形會以一個點爲中心順時針旋轉。兩個多邊形旋轉的速度(rad/s)相同,每個多邊形各有一個旋轉中心。
問這兩個多邊形旋轉過程中是否會發生碰撞
思路
觀察發現,碰撞發生時,肯定是一個多邊形的頂點撞上了另一個多邊形的邊。不妨設多邊形B的頂點撞上了多邊形A的邊(多邊形A的頂點撞上了多邊形B的邊的情況,只需要把A和B對換一下就行了)。我們不妨固定多邊形A不動,讓B繞着A做逆時針公轉,自己做順時針自轉,公轉和自轉的速率相同。
如上圖,設多邊形A的旋轉中心爲P,B的中心爲Q。則B公轉的軌道就是圖上藍色的、以P爲圓心、半徑爲PQ的圓。設黃色點
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 1100
using namespace std;
typedef long long int LL;
struct Point
{
LL x,y;
Point(){}
Point(LL _x,LL _y):x(_x),y(_y){}
}pA[MAXN],pB[MAXN],centerA,centerB;
int n,m;
Point operator-(Point a,Point b)
{
return Point(a.x-b.x,a.y-b.y);
}
Point operator+(Point a,Point b)
{
return Point(a.x+b.x,a.y+b.y);
}
LL cross(Point a,Point b)
{
return a.x*b.y-a.y*b.x;
}
LL dist(Point a,Point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
struct Line
{
Point st,ed;
Line(){}
Line(Point _st,Point _ed):st(_st),ed(_ed){}
};
bool check() //爲了防止被坑爹卡精度,所有的距離全部是實際距離的平方,面積也得是平方
{
LL R=dist(centerA,centerB); //公轉軌道的圓的半徑
for(int i=1;i<=m;i++) //枚舉B上的點i落到了A上面
{
Point tmpC=centerA+(pB[i]-centerB);
for(int j=1;j<=n;j++) //枚舉A上的邊j->j+1
{
Point tmpA=pA[j],tmpB=pA[j%n+1];
LL disA=dist(tmpA,tmpC),disB=dist(tmpB,tmpC);
if(disA-R<=0&&disB-R>=0) //disA和disB中一個比R大,一個比R小,表明A上的邊j->j+1會碰撞上B上的點i
return true;
if(disA-R>=0&&disB-R<=0) //disA和disB中一個比R大,一個比R小,表明A上的邊j->j+1會碰撞上B上的點i
return true;
//if(disA-R<0&&disB-R<0) continue;
if(max(disA,disB)*2>disA+disB+dist(tmpA,tmpB)) continue;
if(cross(tmpC-tmpA,tmpB-tmpA)*cross(tmpC-tmpA,tmpB-tmpA)<=R*dist(tmpA,tmpB)&&disA>=R) //!!!!B上的點i到邊j->j+1的距離小於等於R
return true;
}
}
return false;
}
int main()
{
scanf("%I64d%I64d",¢erA.x,¢erA.y);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%I64d%I64d",&pA[i].x,&pA[i].y);
scanf("%I64d%I64d",¢erB.x,¢erB.y);
scanf("%d",&m);
for(int i=1;i<=m;i++) scanf("%I64d%I64d",&pB[i].x,&pB[i].y);
if(check())
{
printf("YES\n");
return 0;
}
swap(n,m);
swap(centerA,centerB);
swap(pA,pB);
if(check())
{
printf("YES\n");
return 0;
}
printf("NO\n");
return 0;
}