A
题目大意:
给你一个矩形的两个顶点,让你求另外两个顶点。
解题思路:
水题不解释了
我的代码:
#include <cstdio>
using namespace std;
int main (){
int x1,y1,x2,y2;
while (~scanf("%d%d%d%d",&x1,&y1,&x2,&y2)){
int x3,y3,x4,y4;
bool yes=true;
if (x1==x2&&y1!=y2){
int c=y1-y2;
if (c<0) c=-c;
if (x1+c>1000) x3=x4=x1-c;
else x3=x4=x1+c;
y3=y1;y4=y2;
}
if (x1!=x2&&y1==y2){
int c=x1-x2;
if (c<0)c=-c;
if (y1+c>1000) y3=y4=y1-c;
else y3=y4=y1+c;
x3=x1;x4=x2;
}
if (x1!=x2&&y1!=y2){
int c=x1-x2;
int d=y1-y2;
if (c<0) c=-c;
if (d<0) d=-d;
if (c!=d) printf("-1\n"),yes=false;
else {
x3=x1;y3=y2;
x4=x2;y4=y1;
}
}
if (yes){
printf("%d %d %d %d\n",x3,y3,x4,y4);
}
}
return 0;
}
B.
题目大意:
给你n个数,取两个数使得两个数之差最大,问最大差为多少,有几种取法。
解题思路:
水题不解释,但是注意最大值超出int 要使用longlong
我的代码:
#include <cstdio>
#include <iostream>
using namespace std;
long long minx,x,maxn,y;
int n;
int main (){
while (~scanf("%d",&n)){
for (int i=0;i<n;i++){
long long c;cin>>c;
if (i==0){
minx=maxn=c;
x=y=1;
}
else {
if (c==maxn) x++;
else if (c>maxn){
maxn=c;x=1;
}
if (c==minx) y++;
else if (c<minx) {
minx=c;y=1;
}
}
}
if (maxn==minx){
long long kkk=(long long)n*(n-1)/2;
printf("%I64d %I64d\n",maxn-minx,kkk);
}
else printf("%I64d %I64d\n",maxn-minx,x*y);
}
return 0;
}
C.
题目大意:
n个人做k辆车出去玩d天,求出一种坐车方式使得n个人,任意两个人这d天坐车方式都不完全一样。(完全一样就是这d天,每天都坐同一辆车)。
解题思路:
先假设最后一天每个人坐的车都不一样,当然k>=n时这种情况才满足。
如果k<n的时候,我们就让最后一天的车编号对k取模,倒数第二天就是最后一天的车编号除以k。(车的编号从0开始)
倒数第二天操作与倒数第一天一样。(有点类似k进制运算)
最后得到的矩阵中如果有数大于等于k,就表示不可能,否则输出矩阵。
我的代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define maxn 1010
using namespace std;
int a[maxn][maxn];
int main (){
int n,k,d;
while (~scanf("%d%d%d",&n,&k,&d)){
memset(a,0,sizeof(a));
for (int i=0;i<n;i++)
a[d-1][i]=i;
for (int i=d-1;i>0;i--){
for (int j=0;j<n;j++){
a[i-1][j]+=a[i][j]/k;
a[i][j]%=k;
}
}
int yes=true;
for (int i=0;i<d;i++)
for (int j=0;j<n;j++)
if (a[i][j]>=k) {
printf("-1\n"),yes=false;
break;
}
if (yes){
for (int i=0;i<d;i++)
for (int j=0;j<n;j++)
printf("%d%c",a[i][j]+1,j==n-1?'\n':' ');
}
}
return 0;
}
D
题目大意:
给你n个数,规定两个函数f(x),g(x),f(x)为1到x这些数中与ax相等数的个数,g(x)为为x到n这些数中与ax相等数的个数。
问你存在多少组(x,y) f(x)>g(y)。
解题方法:
f(x),g(x)按照一般方法求就可以了。
但是最后求多少组的时候要使用树状数组,否则会TLE。
是树状数组的简单应用。
我的代码:
#include <cstdio>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
map <int ,int >vis;
int num[1000010],a[1000010],b[1000010];
int n;
int tree[1000010];
int add(int x,int v){
for (int i=x;i<1000000;i+=i&(-i))
tree[i]+=v;
return 0;
}
int sum(int x){
if (x==0) return 0;
int ans=0;
for (int i=x;i>0;i-=i&(-i))
ans+=tree[i];
return ans;
}
int main (){
//freopen("test.in","r",stdin);
while (~scanf("%d",&n)){
vis.clear();
for (int i=0;i<n;i++){
scanf("%d",&num[i]);
vis[num[i]]++;
a[i]=vis[num[i]];
}
vis.clear();
for (int i=n-1;i>=0;i--){
vis[num[i]]++;
b[i]=vis[num[i]];
}
//for (int i=0;i<n;i++)
// cout<<a[i]<<" ";cout<<endl;
//for (int i=0;i<n;i++)
// cout<<b[i]<<" ";cout<<endl;
long long ans=0;
memset(tree,0,sizeof(tree));
for (int i=n-1;i>=0;i--){
//cout<<a[i]-1<<" "<<sum(a[i]-1)<<endl;
ans+=sum(a[i]-1);
add(b[i],1);
}
cout<<ans<<endl;
}
return 0;
}
E.
题目大意:
给你m条边,每条边有权重w,让你找到一个最长路线,在这条路线上权重递增,问最长路线的长度。
解题方法:
先将边从小到大排序,然后就是dp了,dp[i]=max(dp[i],dp[u]) (第i条边 u->v)
我的代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define maxn 300010
using namespace std;
struct edge{
int x,y,w;
}edg[maxn];
int num[maxn];
int dp[maxn];
int n,m;
int cmp(edge a,edge b){
return a.w<b.w;
}
int main (){
//freopen("test.in","r",stdin);
while (~scanf("%d%d",&n,&m)){
memset(edg,0,sizeof(edg));
memset(num,0,sizeof(num));
memset(dp,0,sizeof(dp));
for (int i=0;i<m;i++){
scanf("%d%d%d",&edg[i].x,&edg[i].y,&edg[i].w);
}
sort(edg,edg+m,cmp);
int ans=0,begins=0;
for (int i=0;i<m;i++){
dp[i]=num[edg[i].x]+1;
if (edg[i].w!=edg[i+1].w){
for (int j=begins;j<=i;j++)
num[edg[j].y]=max(num[edg[j].y],dp[j]);
begins=i+1;
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return 0;
}