这次又是悲剧,C题没想到进制去,用这个记录下。
A:
注意细节即可,比如重合等的情况
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int x1,y,x2,y2;
int main()
{
while(scanf("%d%d%d%d",&x1,&y,&x2,&y2)!=EOF)
{
if(x1==x2&&y==y2)
{
printf("-1\n");
continue;
}
if(x1==x2)
{
int len=abs(y-y2);
printf("%d %d %d %d\n",x1+len,y,x2+len,y2);
}
else if(y==y2)
{
int len=abs(x1-x2);
printf("%d %d %d %d\n",x1,y-len,x2,y2-len);
}
else if(abs(x1-x2)==abs(y-y2))
{
int len=abs(x1-x2);
printf("%d %d %d %d\n",x1,y2,x2,y);
}
else
printf("-1\n");
}
return 0;
}
B:
答案肯定是最大值减最小值,只需要统计最大值和最小值有多少个就行了,答案是他们的乘积。但是需要考虑他们都相等的情况,那么此时的最大差值为1,方法数应该为n*(n-1)/2
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e5+1000;
const int inf=1<<29;
int n,a[maxn];
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
if(a[0]==a[n-1])
{
printf("0 %I64d\n",(long long)n*(n-1)/2);
continue;
}
long long cnta=-1,cntb=-1;
for(int i=1;i<n;i++)
if(a[i]!=a[i-1])
{
cnta=i;
break;
}
for(int i=n-2;i>=0;i--)
if(a[i]!=a[i+1])
{
cntb=n-i-1;
break;
}
printf("%d %I64d\n",a[n-1]-a[0],cnta*cntb);
}
return 0;
}
C题:
比赛的时候确实没想到用进制数来,其实纵向的话确实是一个k 进制的数,那么要判断的就是看是否能用长度为d的k进制数是否有大于或等于n个,这点想通了就简单了
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1100;
int n,k,d;
int ans[maxn][maxn];
int main()
{
while(scanf("%d%d%d",&n,&k,&d)!=EOF)
{
long long sum=1;
bool is=false;
for(int i=0;i<d;i++)
{
sum*=k;
if(sum>=n)
{
is=true;
break;
}
}
if(!is)
{
printf("-1\n");
continue;
}
for(int i=0;i<d;i++)
ans[i][0]=1;
for(int i=1;i<n;i++)
{
for(int j=0;j<d;j++)
ans[j][i]=ans[j][i-1];
ans[d-1][i]++;
for(int j=d-1;j>=0;j--)
{
if(ans[j][i]>k)
{
ans[j][i]=1;
ans[j-1][i]++;
}
else
break;
}
}
for(int i=0;i<d;i++)
for(int j=0;j<n;j++)
printf("%d%c",ans[i][j],j==n-1?'\n':' ');
}
return 0;
}
D题:
这个题明显可以用树状数组维护,我的思路是先离散化,然后统计各个数的总次数,然后依次从前往后扫,每扫一个数检测当前的是否存在满足要求的答案,并且更新树状数组,树状数组里面存的是当前结点之前的可能的出现的次数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
int n,m,a[maxn],b[maxn],t[maxn],cnt_pre[maxn],cnt_last[maxn];
int lowbit(int x)
{
return x&(-x);
}
void Update(int x,int val)
{
for(;x<n;x+=lowbit(x))
t[x]+=val;
}
int Sum(int x)
{
int ans=0;
for(;x>0;x-=lowbit(x))
ans+=t[x];
return ans;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(t,0,sizeof(t));
memset(cnt_pre,0,sizeof(cnt_pre));
memset(cnt_last,0,sizeof(cnt_last));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
cnt_last[a[i]]++;
}
long long ans=0;
for(int i=1;i<=n;i++)
{
int val=Sum(cnt_last[a[i]]);
ans+=max(i-1,0)-val;
cnt_last[a[i]]--;
cnt_pre[a[i]]++;
Update(cnt_pre[a[i]],1);
}
printf("%I64d\n",ans);
}
return 0;
}
E题:
开始我用的从小到大枚举边,然后更新边相连的点,然后果断TLE。后来发现可以枚举边,然后记录点的最大花费值和当前边数值,然后每次进行择优合并更新就行了。需要注意的是处理边权值相等的情况, 有时候会漏掉一些情况
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=1<<29;
const int maxn=3e5+10;
struct Edge
{
int from;
int to;
int cost;
Edge(){}
Edge(int sf,int st,int sc):from(sf),to(st),cost(sc){}
bool operator < (const Edge &a)const
{
return cost<a.cost;
}
}E[maxn];
int n,m,last[maxn],from_cnt[maxn],from_val[maxn];
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(from_cnt,0,sizeof(from_cnt));
memset(from_val,-1,sizeof(from_val));
memset(last,0,sizeof(last));
for(int i=0;i<m;i++)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
E[i]=Edge(u,v,c);
}
sort(E,E+m);
int ans=1;
for(int j=0;j<m;j++)
{
if(from_val[E[j].to]==-1)
{
from_val[E[j].to]=E[j].cost;
from_cnt[E[j].to]=1;
}
if(from_val[E[j].from]==-1)
continue;
if(E[j].cost>from_val[E[j].from])
{
if(from_cnt[E[j].to]<from_cnt[E[j].from]+1)
{
if(E[j].cost!=from_val[E[j].to])
last[E[j].to]=from_cnt[E[j].to];
from_cnt[E[j].to]=from_cnt[E[j].from]+1;
from_val[E[j].to]=E[j].cost;
ans=max(ans,from_cnt[E[j].to]);
}
}
else if(E[j].cost==from_val[E[j].from])
{
if(!last[E[j].from])
continue;
if(from_cnt[E[j].to]<last[E[j].from]+1)
{
from_cnt[E[j].to]=last[E[j].from]+1;
from_val[E[j].to]=E[j].cost;
ans=max(ans,from_cnt[E[j].to]);
}
}
}
printf("%d\n",ans);
}
return 0;
}