A略
题意:n*m矩阵,跳蚤只能横向竖向跳,每步能跳s,可以跳任意步,问可以达到最多格子的起始点有多少。
分析:行和列没有关联,设行可达最多格的有a格,列b格。若(n-1)整除s,a=(n-1)/s+1,否则,a=((n-1)/s+1)*((n-1)%s+1);列同理。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
LL n,m,s;
LL get(LL p)
{
if(s>=p||s==1)
return p;
if((p-1)%s==0)
return (p-1)/s+1;
else
return ((p-1)/s+1)*((p-1)%s+1);
}
int main()
{
cin>>n>>m>>s;
LL a=get(n);
LL b=get(m);
cout<<a*b<<endl;
return 0;
}
题意:n节课程,每节课程有一个时间段,课程的时间会重复,最多只能删除一节课程,使所有课程都不冲突,输出可以删除的课程编号,否则输出0;
分析:这种题一般是找区间间的关系。此题可以先按左端从小到大排序,从左到右遍历,并不断更新左端点a和右端点b,若有两节课冲突,则可能有4种情况,1.第一节可删除,第二节不可删除 2.第二节可删除,第一节不可删除 3.都可删除 4.都不可删除。(判断方法用a,b 与下一区间比较即可),若为情况4,结果为0,若情况为1,2,3,继续遍历,还有冲突结果为0,没有则输出可删除课程编号。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define PI acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=5005;
int n;
struct Node
{
int l,r;
int id;
bool operator<(const Node& u)const
{
return l<u.l;
}
}node[maxn];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&node[i].l,&node[i].r);
node[i].id=i;
}
sort(node,node+n);
int a=-1,b=-1;
bool flag=true;
bool ww=false;
int u=node[0].id;
int hand=node[0].l,tail=node[0].r;
for(int i=1;i<n;i++)
{
if(node[i].l<tail)
{
if(ww==true)
{
flag=false;
break;
}
ww=true;
if(i==n-1)
{
a=u;b=node[i].id;
}
else
{
int th=hand,tt=tail;
int er,et,v;
hand=node[i].l;
tail=node[i].r;
if(node[i+1].l>=tail)
{
a=u;
er=hand;et=tail;v=node[i].id;
}
hand=th;tail=tt;
if(node[i+1].l>=tail)
{
if(a!=-1)
b=node[i].id;
else
a=node[i].id;
er=hand;et=tail;v=u;
}
if(a==-1&&b==-1)
{
flag=false;
break;
}
hand=er;tail=et;u=v;
}
continue;
}
hand=node[i].l;tail=node[i].r;u=node[i].id;
}
if(flag==false)
printf("0\n");
else
{
int d=0;
if(a!=-1)
d++;
if(b!=-1)
d++;
if(d==1)
printf("%d\n%d\n",d,a+1);
else if(d==2)
{
if(a>b)
swap(a,b);
printf("%d\n%d %d\n",d,a+1,b+1);
}
else
{
printf("%d\n",n);
for(int i=1;i<=n;i++)
{
if(i==n)
printf("%d\n",i);
else
printf("%d ",i);
}
}
}
return 0;
}
题意:给出n个点的坐标,m个圆的圆心坐标和半径,点不在圆上,有k次询问,每次询问需要答出从一点到另一点需穿过多少个圆(不一定是直线)。
分析:先预处理每个点与每个圆的关系(圆内或圆外),询问两点,遍历这两点与圆的关系,不同则加1.
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define PI acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=1005;
int n,m,k;
int point[maxn][2];
int fence[maxn][3];
int guan[maxn][maxn];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d%d",&point[i][0],&point[i][1]);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&fence[i][0],&fence[i][1],&fence[i][2]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
LL a=point[i][0],b=fence[j][1],c=point[i][1],d=fence[j][2];
LL u=(a-b)*(a-b)+(c-d)*(c-d);
LL v=LL(fence[j][0])*LL(fence[j][0]);
if(u>v)
guan[i][j]=1;//圆外
else
guan[i][j]=0;//圆内
}
}
int a,b;
for(int i=0;i<k;i++)
{
scanf("%d%d",&a,&b);
int ans=0;
for(int j=1;j<=m;j++)
{
if(guan[a][j]!=guan[b][j])
ans++;
}
printf("%d\n",ans);
}
return 0;
}
E.cf31D Chocolate 几何
题意:有一块w*h的巧克力,切k刀,每一刀横切或竖切,并每一刀使巧克力块数加1,问k刀之后各块巧克力面积,按升序输出。
分析:为了把线变成点能够标记,把长宽都乘2,另外计算机表示矩阵的行与坐标系表示的y轴相反,变换一下就可以了。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define PI acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=100005;
int d[205][205];
bool vis[205][205];
int num[maxn];
int e=0;
int ans;
int w,h,n;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
void dfs(int r,int c);
int main()
{
scanf("%d%d%d",&w,&h,&n);
memset(vis,0,sizeof(vis));
memset(d,-1,sizeof(d));
for(int i=1;i<2*h;i+=2)
{
for(int j=1;j<2*w;j+=2)
d[i][j]=0;
}
int x1,y1,x2,y2;
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1==0)
x1=1;
else
x1=2*x1;
if(x2==0)
x2=1;
else
x2=2*x2;
y1=(h-y1)*2;y2=(h-y2)*2;
if(y1==0)y1=1;
if(y2==0)y2=1;
if(y1==y2)
{
for(int j=x1;j<=x2;j++)
d[y1][j]=1;
}
else
{
for(int j=y2;j<=y1;j++)
d[j][x1]=1;
}
}
for(int i=1;i<2*h;i+=2)
{
for(int j=1;j<2*w;j+=2)
{
if(vis[i][j]==0)
{
ans=0;
dfs(i,j);
num[e++]=ans;
}
}
}
sort(num,num+e);
for(int i=0;i<e;i++)
{
if(i==e-1)
printf("%d\n",num[i]);
else
printf("%d ",num[i]);
}
return 0;
}
void dfs(int r,int c)
{
vis[r][c]=1;
if(!(r>=1&&r<=2*h)||!(c>=1&&c<=2*w))
return;
if(d[r][c]==1)
return;
if(d[r][c]==0)
ans++;
for(int i=0;i<4;i++)
{
if(vis[r+dir[i][0]][c+dir[i][1]]==0)
dfs(r+dir[i][0],c+dir[i][1]);
}
}