总结
教上场更自闭一些,榜歪了,题过的也不多,死磕K不出。
开局两边同时读到签到,我过了D,lls他们过了C
之后跟榜开k,把我干掉线了,四个小时写了快十份K代码。深刻检讨一下,属实没学过拓扑搞这个的技巧以及链表技巧,成功避开两个正解。而且卡题卡太死,导致团队一直少个人,应该检讨。
lls和carry过了F计算几何,是一个球的体积交,希望carry在计算几何的路上越走越远,我就先run了。
C 题意
n*m方格,挨个划线(相邻两点),要求不能合成多边形,依次进行,无法连线失败,问先手能不能赢。n,m<=4
C 思路
郎老师他们推结论极速签到,我赛后补题唯唯诺诺n*m枚举,我们都有光明的未来
C 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k,q;
int arr[maxn];
void solve(){
cin>>n>>m;
if(n>m) swap(n,m);
if(n==m&&(n==1||n==3)){
cout<<"NO"<<endl;return;
}
if(n==1&&m==3){
cout<<"NO"<<endl;return;
}
cout<<"YES"<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
//cin>>tn;
while(tn--){
solve();
}
}
D 题意
打牌,俩人,每人两张,28最大,两张一样大于两张不一样,两张都一样比具体大小,两张都不一样比加和模10大小,加和模10一样大比第二张大小
D 思路
条件结构入门题,建议放到带学c++考试
D 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k,q;
int arr[maxn];
int a,b,c,d;
void first(){
cout<<"first"<<endl;
}
void second(){
cout<<"second"<<endl;
}
void tie(){
cout<<"tie"<<endl;
}
void solve(){
cin>>a>>b>>c>>d;
if(a>b) swap(a,b);
if(c>d) swap(c,d);
if(a==c&&b==d){
tie();
return ;
}
if(a==2&&b==8){
first();
return ;
}
if(c==2&&d==8){
second();
return ;
}
if(a==b&&c==d){
if(a>c){
first();
}
else if(a<c){
second();
}
else
tie();
return ;
}
if(a==b){
first();
return ;
}
if(c==d){
second();
return ;
}
int t1=(a+b)%10,t2=(c+d)%10;
if(t1>t2){
first();
return;
}
if(t1<t2){
second();
return ;
}
if(b>d){
first();
return ;
}
else if(b<d){
second();
return ;
}
else{
tie();
return ;
}
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
while(tn--){
solve();
}
}
I 题意
20*20的两块地图,有墙有空地,控制两只企鹅一起走,一起上下或者相对走相离走,左企鹅从右下到右上,右企鹅左下到坐上。非法操作会被企鹅忽略(但有意义,左企鹅无效没准右企鹅有效呢),输出最短步数,方案串(LRUD字典序最小),粉刷了走过的路径的地图。
i 思路
榜歪了,明明一挺简单搜索。
BFS模拟,注意字典序最小,输出方案要正向输出,倒序走会有无效方案干扰。
i 代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
int n,m,k;
char mp1[55][55],mp2[55][55];
char ans1[55][55],ans2[55][55];
int dxy[][2][2]={{{1,0},{1,0}},{{0,-1},{0,1}},{{0,1},{0,-1}},{{-1,0},{-1,0}}};
string way[]={"D","L","R","U"};
bool vis[21][21][21][21];
struct Node{
int x1,y1,x2,y2;
string s;
}ans;
bool judge1(Node x){
return !(mp1[x.x1][x.y1]=='#');
}
bool judge2(Node x){
return !(mp2[x.x2][x.y2]=='#');
}
bool ok(Node x){
return x.x1==1&&x.y1==20&&x.x2==1&&x.y2==1;
}
void deal(int &x1,int &y1,int &x2,int &y2,int w){
Node to={x1+dxy[w][0][0],y1+dxy[w][0][1],x2+dxy[w][1][0],y2+dxy[w][1][1],""};
if(!judge1(to)) to.x1=x1,to.y1=y1;
if(!judge2(to)) to.x2=x2,to.y2=y2;
x1=to.x1,y1=to.y1,x2=to.x2,y2=to.y2;
}
void print(){
int x1=20,y1=20,x2=20,y2=1;
mp1[x1][y1]=mp2[x2][y2]='A';
for(auto i:ans.s){
if(i=='D')
deal(x1,y1,x2,y2,0);
if(i=='L')
deal(x1,y1,x2,y2,1);
if(i=='R')
deal(x1,y1,x2,y2,2);
if(i=='U')
deal(x1,y1,x2,y2,3);
mp1[x1][y1]=mp2[x2][y2]='A';
}
for(int i=1;i<=20;i++){
for(int j=1;j<=20;j++)
cout<<mp1[i][j];
cout<<' ';
for(int j=1;j<=20;j++)
cout<<mp2[i][j];
cout<<endl;
}
}
queue<Node>q;
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.ans","w",stdout);
#endif
for(int i=0;i<30;i++)
for(int j=0;j<30;j++)
mp1[i][j]=mp2[i][j]='#';
for(int i=1;i<=20;i++){
for(int j=1;j<=20;j++)
cin>>mp1[i][j];
for(int j=1;j<=20;j++)
cin>>mp2[i][j];
}
q.push({20,20,20,1,""});
vis[20][20][20][1]=1;
while(q.size()){
auto now=q.front();q.pop();
if(ok(now)){
ans=now;
break;
}
for(int w=0;w<4;w++){
Node to={now.x1+dxy[w][0][0],now.y1+dxy[w][0][1],now.x2+dxy[w][1][0],now.y2+dxy[w][1][1],now.s+way[w]};
if(!judge1(to)) to.x1=now.x1,to.y1=now.y1;
if(!judge2(to)) to.x2=now.x2,to.y2=now.y2;
if(!vis[to.x1][to.y1][to.x2][to.y2]){
q.push(to);
vis[to.x1][to.y1][to.x2][to.y2]=1;
}
}
}
cout<<ans.s.size()<<endl<<ans.s<<endl;
print();
}
F 题意
两个三维点,每个点有两个点p1,p2,要求其到p1的距离大于p2距离k倍,问区域交
F 思路
给出的是一个球的等价定义,就是求球的体积交
F 代码
#include <bits/stdc++.h>
#define ll long long
const double pi = acos(-1);
double x_1,x_2,x_3,y_1,y_2,y_3,z_1,z_2,z_3,x_4,y_4,z_4,k_1,k_2,D1,D2,E1,E2,F1,F2,G1,G2;
using namespace std;
int main()
{
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
double x1,x2,y1,y2,z1,z2,r1,r2;
int T;
cin>>T;
while (T--)
{
cin>>x_1>>y_1>>z_1>>x_2>>y_2>>z_2>>x_3>>y_3>>z_3>>x_4>>y_4>>z_4>>k_1>>k_2;
x1=(x_2*k_1*k_1-x_1)/(k_1*k_1-1);
D1=x1*(-2);
y1=(y_2*k_1*k_1-y_1)/(k_1*k_1-1);
E1=y1*(-2);
z1=(z_2*k_1*k_1-z_1)/(k_1*k_1-1);
F1=z1*(-2);
G1=((k_1*k_1*x_2*x_2-x_1*x_1)+(k_1*k_1*y_2*y_2-y_1*y_1)+(k_1*k_1*z_2*z_2-z_1*z_1))/(k_1*k_1-1);
r1=sqrt(D1*D1+E1*E1+F1*F1-G1*4)/2;
//cout<<D1<<" "<<E1<<" "<<F1<<" "<<G1<<endl;
//cout<<a[1].x<<" "<<a[1].y<<" "<<a[1].z<<" "<<a[1].r<<endl;
//scanf("%lf%lf%lf%lf", &s.x, &s.y, &s.z, &s.r);
x2=(x_4*k_2*k_2-x_3)/(k_2*k_2-1);
D2=x2*(-2);
y2=(y_4*k_2*k_2-y_3)/(k_2*k_2-1);
E2=y2*(-2);
z2=(z_4*k_2*k_2-z_3)/(k_2*k_2-1);
F2=z2*(-2);
G2=((k_2*k_2*x_4*x_4-x_3*x_3)+(k_2*k_2*y_4*y_4-y_3*y_3)+(k_2*k_2*z_4*z_4-z_3*z_3))/(k_2*k_2-1);
r2=sqrt(D2*D2+E2*E2+F2*F2-G2*4)/2;
//cout<<x1<<" "<<y1<<" "<<z1<<" "<<r1<<endl;
//cout<<x2<<" "<<y2<<" "<<z2<<" "<<r2<<endl;
double sum=4.00/3.00*pi*r1*r1*r1+4.00/3.00*pi*r2*r2*r2;
double ans=0;
double dis=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)); //球心距离
if(dis>=r1+r2) //没有交到的地方
{
ans=0;
}
else if (dis+r1<=r2)//重合
{
ans=(4.00/3.00)*pi*r1*r1*r1;
}
else if(dis+r2<=r1)
{
ans=(4.00/3.00)*pi*r2*r2*r2;
}
else //相交
{
double cal=(r1*r1+dis*dis-r2*r2)/(2.00*dis*r1);
double h=r1*(1-cal);
ans+=(1.00/3.00)*pi*(3.00*r1-h)*h*h;
cal=(r2*r2+dis*dis-r1*r1)/(2.00*dis*r2);
h=r2*(1.00-cal);
ans+=(1.00/3.00)*pi*(3.00*r2-h)*h*h;
}
printf("%.10f\n",ans);
}
return 0;
}
K 题意
对一个排列进行单调栈处理,b数组为单调栈处理完每个位置后的大小,给出几个b的值,还原排列。
K 思路
正解给了链表和拓扑,链表目前看不懂,会补的。
拓扑是这样的,我们模拟单调栈,采取这样的策略,没有b约束就直接扔ai进去,有的话判断下是否合法,合法就弹出该弹的数据,将ai扔进去。在这样的过程中我们已经得到了大小关系,就是每次扔ai,他比仍之前的栈顶大,每次弹出,弹出的值都比ai大。我们对大于关系建边,跑拓扑排序即可。
K 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=2000505;
const int inf=0x3f3f3f3f;
int n,m,k,q;
int ans[maxn];
int b[maxn];
vector<int>e[maxn];
int in[maxn];
stack<int>s;
void solve(){
cin>>n>>m;
while(m--){
int t1,t2;
cin>>t1>>t2;
b[t1]=t2;
}
for(int i=1;i<=n;i++){
if(b[i]){
if((i>2&&b[i]>b[i-1]+1)||b[i]>i){
cout<<-1<<endl;
return;
}
}
else
b[i]=b[i-1]+1;
}
for(int i=1;i<=n;i++){
if(b[i]>s.size()){
if(s.size()){
//cout<<i<<'>'<<s.top()<<endl;
e[i].push_back(s.top());
in[s.top()]++;
}
s.push(i);
}
else{
while(b[i]<=s.size()){
// cout<<s.top()<<'>'<<i<<endl;
e[s.top()].push_back(i);
in[i]++;
s.pop();
}
if(s.size()){
// cout<<i<<'>'<<s.top()<<endl;
e[i].push_back(s.top());
in[s.top()]++;
}
s.push(i);
}
}
queue<int>q;
for(int i=1;i<=n;i++){
if(!in[i]) q.push(i);
}
int now=n;
while(q.size()){
int x=q.front();q.pop();
ans[x]=now--;
for(auto y:e[x]){
in[y]--;
if(in[y]==0)
q.push(y);
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
while(tn--){
solve();
}
}