题目来源:https://ac.nowcoder.com/acm/contest/3007#question
这场又有好多AK的,我tcl… 可能会补2题左右,保证不咕~
A - 配对
先对两个序列从小到大排序,假如选第k大的,那我们肯定不能让第k大的这个碰到两个序列前1 - k 的元素,忽略他们,然后后面的头+尾 排个序取最小值
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int f[N],g[N];
int p[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n); r(m);
FOR(i,1,n) r(f[i]);
FOR(i,1,n) r(g[i]);
sort(f+1,f+n+1);
sort(g+1,g+n+1);
FOR(i,n-m+1,n){
p[i-n+m]=f[i]+g[n-i+n-m+1];
}
sort(p+1,p+m+1);
cout<<p[1]<<endl;
return 0;
}
B - 图
这题应该就是类似于记忆化搜索,搜过的点标记上它的值,然后可以O(n)解决,难点就在于环的处理。但是这样想,从一个点开始搜,它最终的结局要么是撞到自己刚刚搜到的点成环,要么是碰到已经搜过的点把这个点的值+1即可。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int to[N];
bool vis[N];
int step[N];
int num[N];
int ans,loop;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int dfs(int x,int stp)
{
//cout<<x<<' '<<stp<<endl;
step[x]=stp;
int t=to[x];
if(vis[t]==0){
vis[t]=1;
int res=dfs(t,stp+1);
if(loop!=0){
if(loop==x){
loop=0;
}
return num[x]=res;
}
else{
return num[x]=res+1;
}
}
else{
if(num[t]>0) return num[x]=num[t]+1;
else if(num[t]==0){
loop=t;
if(t==x) loop=0;
return num[x]=step[x]-step[t]+1;
}
}
}
int main()
{
r(n);
FOR(i,1,n){
r(to[i]);
}
ans=0;
FOR(i,1,n){
if(!vis[i]){
vis[i]=1;
loop=0;
dfs(i,1);
}
}
FOR(i,1,n){
ans=max(num[i],ans);
// cout<<num[i]<<' ';
}
//cout<<endl;
cout<<ans<<endl;
return 0;
}
C - 汉诺塔
这题真的感觉我最近在哪里做过类似的题,应该是cf上!
首先对x从大到小排序,然后从左到右加入set,加之前先看他能不能在set中找到比他的y小的最大的点放在他上面
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
struct node
{
int x,y,id;
bool operator< (node a){
return x<a.x;
}
}f[N];
int val[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
FOR(i,1,n){
r(f[i].x); r(f[i].y);
f[i].id=i;
}
sort(f+1,f+n+1);
set<pt> s;
int num=0;
FOR(i,1,n){
if(s.size()){
set<pt>::iterator it=s.lower_bound(mp(f[i].y,0));
if(it!=s.begin()){
it--;
if(val[it->second]==0){
val[it->second]=++num;
val[f[i].id]=num;
}
else{
val[f[i].id]=val[it->second];
}
s.erase(it);
}
}
s.insert(mp(f[i].y,f[i].id));
}
FOR(i,1,n){
if(val[i]==0) val[i]=++num;
}
cout<<num<<endl;
FOR(i,1,n) cout<<val[i]<<' ';
cout<<endl;
return 0;
}
D - 重排列
反着思考,我们找不满足的 和总数相减即可
先对两个序列排序,这不会影响结果(可以理解的吧)
然后只要我们满足任意一个地方大于 他就是不满足的 没问题吧.
遍历一遍,对于当前的点i 我们找比这个点大的有多少个(二分搜索) 然后在这个点用比他大的点,那么后面任意怎么排都行ans=(ans+mult*cnt_h%mod*cc[n-i]%mod)%mod;
但是这个mult是干嘛的? 如果我们选不大于这个点的那就要看下一个点大不大嘛
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,char> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
LL n,m;
int f[N];
int g[N];
LL cc[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
cc[0]=1;
FOR(i,1,n){
cc[i]=cc[i-1]*i%mod;
}
FOR(i,1,n){
r(f[i]);
}
FOR(i,1,n) r(g[i]);
sort(g+1,g+n+1);
sort(f+1,f+n+1);
LL ans=0,mult=1;
FOR(i,1,n){
LL cnt_l=upper_bound(f+i,f+n+1,g[i])-f-i;
LL cnt_h=(n-i+1)-cnt_l;
ans=(ans+mult*cnt_h%mod*cc[n-i]%mod)%mod;
//cout<<ans<<endl;
if(cnt_h==n-i+1||cnt_h==0){
break;
}
else{
mult=mult*cnt_l%mod;
}
}
LL res=(cc[n]-ans+mod)%mod;
cout<<res<<endl;
return 0;
}
E - 立方数
狂T不止
F - 十字阵列
计算每次操作的贡献即可,因为每次操作的每个格子的i+j是很容易算出来的(m*x+n*y-x-y)+(n+1)*n/2+(m+1)*m/2;
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int f[N],g[N];
int p[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
int k;
r(n); r(m); r(k);
LL ans=0;
FOR(i,1,k){
int x,y,z;
rrr(x,y,z);
LL dmg=(m*x+n*y-x-y)+(n+1)*n/2+(m+1)*m/2;
ans=(ans+dmg*z%mod)%mod;
//cout<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}
G - 括号序列
就是括号匹配…
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
char str[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
int t;
r(t);
while(t--){
r(n);
scanf("%s",str+1);
stack<char> s;
FOR(i,1,n){
if(s.size()){
if(str[i]==')'&&s.top()=='('){
s.pop();
}
else{
s.push(str[i]);
}
}
else{
s.push(str[i]);
}
}
cout<<s.size()<<endl;
}
return 0;
}
H - 云
I - 导航系统
J - 签到题
设三个圆的半径分别为a b c,那三个边长即为a+b,b+c,a+c
(x,y,z为输入的边长)如果能构成三角形,那么很容易知道一边小于两边之和,设
,其中a b c一定都大于0 故一定存在!
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
int a,b,c;
rrr(a,b,c);
double tot=(a+b+c)*1.0/2;
if(a+b>c&&a+c>b&&b+c>a){
if(tot>a&&tot>b&&tot>c){
cout<<"Yes\n";
double f[4];
f[1]=tot-a;
f[2]=tot-b;
f[3]=tot-c;
sort(f+1,f+4);
printf("%.2f %.2f %.2f\n",f[1],f[2],f[3]);
}
else{
cout<<"No\n";
}
}
else{
cout<<"wtnl\n";
}
return 0;
}