A. Hard Way
题目大意:给你一个位于第一象限的三角形,问不能由x轴上的点沿直线达到的线段长度。
首先要满足题意三角形一定得是个倒三角形,而且最上面的边必须平行与x轴,这样只需要输出这条边的长度即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
int read()
{
int x=1,res=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
x=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
res=res*10+(c-'0');
c=getchar();
}
return res*x;
}
struct node{
double x,y;
}g[maxn];
bool cmp(node a,node b)
{
return a.y>b.y;
}
void solve()
{
double x[4],y[4];
cin>>g[1].x>>g[1].y>>g[2].x>>g[2].y>>g[3].x>>g[3].y;
sort(g+1,g+1+3,cmp);
if(g[1].y==g[2].y){
printf("%.9lf\n",abs(g[1].x-g[2].x));
}
else puts("0");
}
int main()
{
int t=read();
while(t--)
solve();
}
B. Power Walking
题目大意:给你一个序列,然后分别将其分成1~n份,问每一次分后,求每一份中不同数的个数的和最小是多少。
我们要使得每一份中不同的数的个数尽量小,那么每一份中就要尽可能多的含有相同的数,因此,我们统计序列中不同的数的个数,记为cnt,那么当分成的份数小于等于cnt时,答案就是cnt,我们只需要将相等的数分在同一份中即可,而份数大于cnt时,答案就等于分的份数。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
int read()
{
int x=1,res=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
x=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
res=res*10+(c-'0');
c=getchar();
}
return res*x;
}
int cnt[maxn],a[maxn],b[maxn],f[maxn];
void solve()
{
int n=read();
for(int i=1;i<=n;i++){
cnt[i]=0;
f[i]=0;
}
for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
sort(a+1,a+1+n);
int tott=unique(a+1,a+1+n)-a-1;
for(int i=1;i<=n;i++)
{
if(i<=tott)
printf("%d ",tott);
else printf("%d ",i);
}puts("");
}
int main()
{
int t=read();
while(t--)
solve();
}
C.Great Sequence
题目大意:给你一个序列和一个数x,每次操作可向序列中添加任何数,要求将序列中的数两两配对且商为x,求最小操作次数。
我们可以从小到大依次寻找匹配对象,如果某个数乘以x在序列中出现,那么这两个数就可以直接配对,否则我们就需要额外添加一个数进行配对。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define int long long
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
int read()
{
int x=1,res=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
x=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
res=res*10+(c-'0');
c=getchar();
}
return res*x;
}
map<int,int>s;
int a[maxn];
void solve()
{
int n=read(),x=read(),ans=0,aa;
s.clear();
for(int i=1;i<=n;i++) {
a[i]=read();
s[a[i]]++;
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
if(!s[a[i]]) continue;
if(s[a[i]]&&s[a[i]*x]){
s[a[i]]--;
s[a[i]*x]--;
}
else {
s[a[i]]--;ans++;
}
}
printf("%d\n",ans);
}
signed main()
{
int t=read();
while(t--)
solve();
}
D. Repetitions Decoding
题目大意:每次向序列中连续添加两个相同的元素且两个元素相邻,构造一种添加方案使得序列可以被拆分为多个AA型子序列。
首先每次只能添加两个元素,且两个元素相同,那么如果某个数只出现一次,一定无解。其次我们想要构造合法方案,首先需要找到两个相同的数,我们可以选取序列的第一个元素位置记为
l
l
l,然后找到下一个和第一个数相同的数这个位置记为
r
r
r,然后我们就可以依次添加区间
(
l
,
r
)
(l,r)
(l,r)中的数以此来形成一个AA型序列,比如说ABCDA就可以依次添加BB,CC,DD来构造形成ABCD ABCD DCB这样就可以成功消去两个A个元素,而且每次只需要操作小于n次,这样就可以保证在
O
(
n
2
)
O(n^2)
O(n2)时间复杂度内得出结果,具体实现过程可以使用vector,细节比较多,可能不是很好调。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
int read()
{
int x=1,res=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
x=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
res=res*10+(c-'0');
c=getchar();
}
return res*x;
}
struct node{
int x,y;
}g[maxn];
int a[maxn],nt[maxn],f[maxn],tot1,tot2;
vector<int>s;
void solve()
{
tot1=tot2=0;
int n=read(),pd=0,cnt=0,ans,now=0,tot=n-1;
s.clear();
for(int i=1;i<=n;i++)
{
a[i]=read();
s.push_back(a[i]);
}
for(int i=1;i<=n;i++) nt[i]=0;
for(int i=1;i<=n;i++){
if(nt[i]==-1) continue;
for(int j=i+1;j<=n;j++)
{
if(nt[j]==-1) continue;
if(a[j]==a[i]) {
nt[i]=j;
nt[j]=-1;
break;
}
}
}
for(int i=1;i<=n;i++) if(nt[i]==0) pd=1;
if(pd) {puts("-1");return;}
while(now<=tot){
int x=s[now];
for(int i=now+1;now<=tot;i++){
if(x==s[i]){
for(int j=now+1;j<i;j++){
s.insert(s.begin()+i+j-now,s[j]);
s.insert(s.begin()+i+j-now,s[j]);
g[++tot2]=(node){i+j-now,s[j]};
tot+=2;
}
f[++tot1]=(i-now)*2;
now=(i-now)*2+now;
break;
}
}
}
printf("%d\n",tot2);
for(int i=1;i<=tot2;i++)
printf("%d %d\n",g[i].x,g[i].y);
printf("%d\n",tot1);
for(int i=1;i<=tot1;i++)
printf("%d ",f[i]);
puts("");
}
int main()
{
int t=read();
while(t--)
solve();
return 0;
}