今日这场比赛我们准备的题比较全面,二分+数论+最短路+计算几何+dp+思维+签到题等。有较难的防AK题,也有简单的签到题。为大家准备了一份题解和AC代码。

A - Meeting with Aliens

UVA - 10570

题目意思:让一个成环的序列变成有序的,正序逆序都可以,问最小交换次数。

解题思路:对于一个长度为n的元素互异的序列,通过交换实现有序的最小的交换次数是=n - 被分解成单循环的个数。数据比较小,正着来一遍,反着来一遍,取最小就可以了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 101000
#define mod ((int)1e9+7) const int maxn = + ; int n;
int num[maxn << ];
bool vis[maxn]; void dfs(int st, int a) {
if (vis[a]) return;
vis[a] = true;
dfs(st, num[st + a - ]);
} void dfs2(int st, int a) {
if (vis[a]) return;
vis[a] = true;
dfs2(st, num[st - a + ]);
} int main()
{
//freopen("input.txt", "r", stdin);
while (~scanf("%d", &n) && n) {
for (int i = ; i < n; i++) {
scanf("%d", &num[i]);
num[i + n] = num[i];
} int Max = ; for (int st = ; st < n; st++) {
memset(vis, false, sizeof(vis));
int cnt = ;
for (int i = st; i < st + n; i++) {
if (!vis[num[i]]) {
dfs(st, num[i]);
cnt++;
}
}
Max = Max > cnt ? Max : cnt;
} for (int st = * n - ; st >= n; st--) {
memset(vis, false, sizeof(vis));
int cnt = ;
for (int i = st; i >= st - n + ; i--) {
if (!vis[num[i]]) {
dfs2(st, num[i]);
cnt++;
}
}
Max = Max > cnt ? Max : cnt;
} printf("%d\n", n - Max);
}
return ;
}

B - Bi-shoe and Phi-shoe

LightOJ - 1370

欧拉函数

题意:给定值,求满足欧拉值大于等于这个数的最小的数。

题解:预处理存下来,从x+1(x是幸运数字)开始找第一个出现的素数,那就是最小花费。

/*

 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I have a dream!A AC deram!!
orz orz orz orz orz orz orz orz orz orz orz
orz orz orz orz orz orz orz orz orz orz orz
orz orz orz orz orz orz orz orz orz orz orz */ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<stdlib.h>
using namespace std;
typedef long long LL;
typedef unsigned long long int ull;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + ;
const int maxn = + ;
int euler[];
void Is_prime()
{
memset(euler,,sizeof(euler));
euler[]=;
for(int i=;i<=;i++)
{
if(!euler[i])
{
for(int j=*i;j<+;j+=i)
{
euler[j]=;
}
}
}
}
int main()
{
int T,t=;
scanf("%d",&T);
Is_prime();
while(T--)
{
int n;
scanf("%d",&n);
LL ans=;
for(int i=;i<n;i++)
{
int x;
scanf("%d",&x);
for(int j=x+;;j++)
{
if(!euler[j])
{
ans+=j;
break;
}
}
}
printf("Case %d: %lld Xukha\n",++t,ans);
}
}

C - Highways

POJ - 1751

题意:首行给出N,代表有1~N共N个点。接下来N行,每行两个数x,y,代表第i个点的坐标。接着给出M,接着M行,每行两个数x,y,代表第x个点和第y个点已经联通(即x到y的权值为0),建立最小生成树,输出生成树中权值不为0的边的两端的点的编号。

题解:最坏的情况需要遍历图中的每一条边,很明显的稠密图,优先选用普利姆算法。根据坐标建立无向图,权值设为距离的平方即可,这样可以避免sqrt后权值变为double型,避免精度损失。对于已联通的两点,更新这两点的权值为0即可。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 101000
#define mod ((int)1e9+7)
const int maxn=;
const int INF=0x3f3f3f3f;
int map[maxn][maxn];
int dis[maxn];
int vis[maxn];
int Edge[maxn];//i到Edge[i]是一条生成树内的边
struct node
{
int x;
int y;
} Point[maxn]; //第i个点的坐标
int N;//点的数量
int M;//更新边的数量
void init()
{
scanf("%d",&N);
for(int i=; i<=N; i++)//建图
{
scanf("%d%d",&Point[i].x,&Point[i].y);
for(int j=; j<i; j++)//为什么这里不取sqrt,因为完全没必要
map[i][j]=map[j][i]=(Point[i].x-Point[j].x)*(Point[i].x-Point[j].x)+(Point[i].y-Point[j].y)*(Point[i].y-Point[j].y);
map[i][i]=INF;//自己不可能到自己
}
scanf("%d",&M);
int x,y;
while(M--)//更新图
{
scanf("%d%d",&x,&y);
map[x][y]=map[y][x]=;
}
memset(vis,,sizeof(vis));
vis[]=;
for(int i=; i<=N; i++)
{
dis[i]=map[i][];
Edge[i]=;//初始化为存储i到1的边
}
}
void Prim()
{
for(int i=; i<N; i++)
{
int minn=INF;
int point_minn;
for(int j=; j<=N; j++)
if(vis[j]==&&minn>dis[j])
{
minn=dis[j];
point_minn=j;
}
vis[point_minn]=;
for(int k=; k<=N; k++)
if(vis[k]==&&dis[k]>map[point_minn][k])
{
Edge[k]=point_minn;//这里是输出方式的技巧
dis[k]=map[point_minn][k];
}
if(map[Edge[point_minn]][point_minn])
printf("%d %d\n",Edge[point_minn],point_minn);
}
}
int main()
{
init();
Prim();
return ;
}

D - Maze

CodeForces - 377A

题意:给你一个图,将k个‘.’变成‘X’,使剩下的‘.’仍然连通,图中还有‘#’。

题解:思维关键点是既然他要你修改k个,那么假设一开始有s个,则dfs搜索到k-s个的时候停止就好了,没被搜索到的就是要修改的,这样可以保证剩下的必定连通。

#include <iostream>
#include <cstdio>
#include <cstring>
int n,m,k;
int go[][]={,,,,,-,-,};
char map[][];
int book[][];
using namespace std;
void dfs(int r,int c)
{
if(!k)
return ;
k--;
//map[r][c]='0';
book[r][c]=;//将要修改的标记出来,注意这里不能在回溯过程中再将标记取消
for(int i=;i<;i++)
{
int tr=r+go[i][];
int tc=c+go[i][];
if(tr>=&&tr<n&&tc>=&&tc<m&&!book[tr][tc]&&map[tr][tc]=='.')
{
dfs(tr,tc);
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
getchar();
int t=;
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='.')
t++;
}
getchar();
}
k=t-k;
int flag=;
for(int i=;i<n&&flag;i++)
{
for(int j=;j<m&&flag;j++)
{
if(map[i][j]=='.')//从第一个.开始搜索
{
//book[i][j]=1;
dfs(i,j);
flag=;
} }
}
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
//printf("%d ",book[i][j]);
if(map[i][j]=='.'&&!book[i][j])//没被搜索到的修改
{
putchar('X');
}
//else if(map[i][j]=='.')
//putchar('X');
else
printf("%c",map[i][j]); }
printf("\n");
}
return ;
}

E - Justice Rains From Above

Gym - 101194K

题意:计算几何。在一个三维空间里,法鸡在某一点,她会发射攻击,攻击是一个圆锥,然后给你几个敌人的坐标,问最多能消灭几个敌人。

2016-2017ICPC-China final的题目,问学军的学弟要来的。

大家自行体会一下。

#pragma GCC optimize(2)
#pragma GCC optimize("inline")
#pragma GCC optimize("fast-math")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <tuple>
#include <cmath>
using namespace std; typedef double real;
const real eps = 1e-, pi = acos(-); inline int fcmp(real x, real y) {
return fabs(x - y) < eps ? : x < y ? - : ;
} struct vec {
real x, y;
vec operator + (const vec &b) const { return {x + b.x, y + b.y}; }
vec operator + (void) const { return {x, y}; }
vec operator - (const vec &b) const { return {x - b.x, y - b.y}; }
vec operator - (void) const { return {-x, -y}; }
vec operator * (const vec &b) const
{ return {x * b.x - y * b.y, x * b.y + y * b.x}; }
vec operator * (real b) const { return {x * b, y * b}; }
vec operator / (real b) const { return {x / b, y / b}; }
real dot(const vec &b) const { return x * b.x + y * b.y; }
real det(const vec &b) const { return x * b.y - y * b.x; }
real norm(void) const { return x * x + y * y; }
real len(void) const { return sqrt(norm()); }
real angle(void) const { return atan2(y, x); }
vec unit(void) const { return *this / len(); }
vec perp(void) const { return {-y, x}; }
bool operator < (const vec &b) const
{ return fcmp(x, b.x) ? x < b.x : fcmp(y, b.y) < ; }
bool operator > (const vec &b) const
{ return fcmp(x, b.x) ? x > b.x : fcmp(y, b.y) > ; }
bool operator <= (const vec &b) const
{ return fcmp(x, b.x) ? x < b.x : fcmp(y, b.y) <= ; }
bool operator >= (const vec &b) const
{ return fcmp(x, b.x) ? x > b.x : fcmp(y, b.y) >= ; }
bool operator == (const vec &b) const
{ return fcmp(x, b.x) == && fcmp(y, b.y) == ; }
bool operator != (const vec &b) const
{ return fcmp(x, b.x) != || fcmp(y, b.y) != ; }
}; struct Line {
vec u, v;
}; struct Circle {
vec o;
real r;
}; vec Foot(const Line &l, const vec &p) {
return l.u + l.v * (l.v.dot(p - l.u) / l.v.norm());
} Line Bisector(const vec &a, const vec &b) {
return {(a + b) * 0.5, (b - a).perp()};
} Line Bisector(const vec &u, const vec &v1, const vec &v2) {
vec v = v1 + v2 * sqrt(v1.norm() / v2.norm());
return {u, fcmp(v.norm(), ) ? v : v1.perp()};
} tuple<int, vec> Intersection(const Line &l1, const Line &l2) {
real delta = l1.v.det(-l2.v);
return fcmp(delta, ) ?
make_tuple(, l1.u + l1.v * ((l2.u - l1.u).det(-l2.v) / delta)) :
make_tuple(, vec());
} tuple<int, vec, vec> Intersection(const Circle &c, const Line &l) {
vec h = Foot(l, c.o);
real delta = c.r * c.r - (h - c.o).norm();
if (fcmp(delta, ) == ) {
return make_tuple(, h, vec());
} else if (delta < ) {
return make_tuple(, vec(), vec());
} else {
vec v = l.v * sqrt(delta / l.v.norm());
return make_tuple(, h + v, h - v);
}
} tuple<int, vec, vec> Intersection(const Circle &c1, const Circle &c2) {
real d2 = (c1.o - c2.o).norm(), d = sqrt(d2);
int delta = fcmp(c1.r + c2.r + d, max(max(c1.r, c2.r), d) * );
if (delta == ) {
return make_tuple(, c1.o + (c2.o - c1.o) * (c1.r / d), vec());
} else if (delta < ) {
return make_tuple(, vec(), vec());
} else {
real cosa = (c1.r * c1.r - c2.r * c2.r + d2) / ( * c1.r * d);
real sina = sqrt( - cosa * cosa);
vec v = (c2.o - c1.o) * (c1.r / d);
return make_tuple(, c1.o + v * (vec){cosa, sina},
c1.o + v * (vec){cosa, -sina});
}
} const int maxn = ; struct vec3 {
real x, y, z;
vec3 operator + (const vec3 &b) const { return {x + b.x, y + b.y, z + b.z}; }
vec3 operator + (void) const { return {x, y, z}; }
vec3 operator - (const vec3 &b) const { return {x - b.x, y - b.y, z - b.z}; }
vec3 operator - (void) const { return {-x, -y, -z}; }
vec3 operator * (real b) const { return {x * b, y * b, z * b}; }
vec3 operator / (real b) const { return {x / b, y / b, z / b}; }
real dot(const vec3 &b) const { return x * b.x + y * b.y + z * b.z; }
real norm(void) const { return x * x + y * y + z * z; }
real len(void) const { return sqrt(norm()); }
real angle_xy(void) const { return atan2(y, x); }
real angle_xz(void) const { return atan2(z, x); }
vec3 unit(void) const { return *this / len(); }
}; int n;
real alpha;
vec3 point[maxn]; vec3 RotateXY(const vec3 &a, real b) {
real sinb = sin(b), cosb = cos(b);
return {a.x * cosb - a.y * sinb, a.x * sinb + a.y * cosb, a.z};
} vec3 RotateXZ(const vec3 &a, real b) {
real sinb = sin(b), cosb = cos(b);
return {a.x * cosb - a.z * sinb, a.y, a.x * sinb + a.z * cosb};
} int cnt_event; struct Event {
real time;
int delta;
bool operator < (const Event &b) const {
return fcmp(time, b.time) ? time < b.time : delta > b.delta;
}
} ev[maxn * ]; bool InShape(const vec3 &u) {
real x = RotateXY(u, -u.angle_xy()).angle_xz();
return fcmp(x, pi / - alpha) >= && fcmp(x, pi / + alpha) <= ;
} real key; bool InShape2(const vec3 &u) {
if (u.z < ) return false;
return u.z * u.z >= key * (u.x * u.x + u.y * u.y);
} bool CalcInter(const vec3 &o, real r, real &ans) {
if (fcmp(r, ) == ) {
return false;
}
vec3 v1 = RotateXZ({r, , }, -alpha);
vec3 v2 = RotateXZ({, r, }, -alpha);
if (!InShape(o - v1)) {
return false;
}
int binary_repeat = ;
real low = , high = pi;
while (binary_repeat--) {
real mid = (low + high) * 0.5;
vec3 u = o + v1 * cos(mid) + v2 * sin(mid);
if (InShape2(u)) {
high = mid;
} else {
low = mid;
}
}
ans = low;
return true;
} real Adjust(real x) {
while (fcmp(x, * pi) >= ) {
x -= * pi;
}
while (fcmp(x, ) < ) {
x += * pi;
}
return x;
} int Solve(vec3 ctr) {
real anxy = -ctr.angle_xy();
ctr = RotateXY(ctr, anxy);
real anxz = (pi / - alpha) - ctr.angle_xz();
ctr = RotateXZ(ctr, anxz);
cnt_event = ;
int init_value = ; for (int i = ; i < n; ++i) {
vec3 u = RotateXZ(RotateXY(point[i], anxy), anxz);
vec3 o = ctr * (ctr.dot(u) / ctr.norm());
vec3 ou_ = RotateXZ(u - o, alpha);
vec ou = {ou_.x, ou_.y};
real init_angle = ou.angle(); if (InShape(u)) {
++init_value;
}
real touch_angle;
if (CalcInter(o, ou.len(), touch_angle)) {
ev[cnt_event++] = {Adjust(touch_angle - init_angle), };
ev[cnt_event++] = {Adjust(-touch_angle - init_angle), -};
}
} sort(ev, ev + cnt_event);
int ans = ;
for (int i = ; i < cnt_event; ++i) {
init_value += ev[i].delta;
ans = max(ans, init_value);
}
return ans;
} int main(void) {
int t;
scanf("%d", &t);
for (int id = ; id < t; ++id) {
scanf("%d%lf", &n, &alpha);
alpha *= pi / ;
key = tan(pi / - alpha);
key *= key;
int x0, y0, z0;
scanf("%d%d%d", &x0, &y0, &z0);
for (int i = ; i < n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
x -= x0;
y -= y0;
point[i] = {(real)x, (real)y, (real)z0};
}
int ans = ;
for (int i = ; i < n; ++i) {
ans = max(ans, Solve(point[i]));
}
printf("Case #%d: %d\n", id + , ans);
}
return ;
}

F - 缺失的数据范围

HDU - 6288

题意:给你a,b,k,求满足公式n^a*(⌈log2n⌉)^b<=k,的n的最大值。

思路:二分n,向上取整可以先预处理出2^62,然后直接循环找到b的底数j。要注意精度控制。

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#define INF 0x3f3f3f3f//3f3f3f3f
typedef long long ll;
using namespace std;
ll a,b,k;
ll s[]={};
int check(ll n)
{
int j=;
for(j=;j<=;j++)
if(n<=s[j])break;
long double t=k;
for(int i=;i<b;i++)
{
t=t/(long double)j;
if(t<1.0)return ;
}
for(int i=;i<a;i++)
{
t=t/(long double)n;
if(t<1.0)return ;
}
return ;
}
int main()
{
int ca;
scanf("%d",&ca);
for(int i=;i<=;i++)
{
s[i]=ll(1ll<<i);
}
while(ca--)
{
scanf("%lld%lld%lld",&a,&b,&k);
ll l=,r=k,mid;
ll ans=;
while(r-l>)
{
mid=(l+r)/;
if(check(mid))
{
l=mid;
}
else r=mid-;
}
if(check(r))printf("%lld\n",r);
else printf("%lld\n",l);
}
return ;
}

G - Triangle

HDU - 5914

题意:给你1~n的木棍,问你最少取走几根能使剩下的木棍不能构成三角形

思路:签到题。首先,因为给定的n范围小,所以可以直接暴力。然后,它是一道找规律的题,为了达到取走的木棍数最少,所以尽可能的取最大的。例举出来后,会发现剩下的棍子是编号是个斐波那契数列。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 401000
#define mod ((int)1e9+7)
map<pair<int,int>,int> ma;
int main(){
int a[]={,,,,,,};
int t;
scanf("%d",&t);
int test=;
while(t--){
int n;
scanf("%d",&n);
int ans=;
for(int i=;i<=;i++){
if(a[i]<=n)
ans++;
}
printf("Case #%d: %d\n",test++,n-ans);
}
}

H - Machine

ZOJ - 3805

题意:有n个机器,每个机器有两个输入口输入原料(上和右)和一个输出口输出产物(下),上一个机器的产物可以作为下一个机器的原料,且上一个机器的编号一定要大于下一个机器的编号。两个机器之间可以用'L'型和'I'型的管子相连,问你所有的机器连起来,最小的宽度是多少

思路:一个父节点的宽度就等于Max(上输入口子节点的宽度,右输入口子节点的宽度+1),因此,尽可能的把宽度大的子节点连接在该节点的上输入口。

递归存入每个节点的宽度,就可以得到根节点的宽度

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cmath>
#include <stack>
#include <cstdlib>
using namespace std;
vector <int> ve[];
int dp[];
void dfs(int x){
int len=ve[x].size();
if(len==)//如果其没有子节点
dp[x]=;//则宽度只需要记录它本身所占的
else if(len==){//如果只有一个
dfs(ve[x][]);
dp[x]=dp[ve[x][]];//该节点宽度为其子节点宽度(即放该节点的上面)
}
else{//最多就两个子节点
int a,b;
dfs(ve[x][]);
dfs(ve[x][]);
a=dp[ve[x][]];
b=dp[ve[x][]];
if(a==b){//如果两个子节点的宽度相等,那么该节点宽度为其中一个放在该节点右边的子节点的宽度+其本身所占的
dp[x]=a+;
}
else{//就把宽度值更大的放在该节点的上面,小的放该节点的右边。该节点的宽度即宽度值更大的子节点的宽度
dp[x]=max(a,b);
}
}
}
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++)
ve[i].clear();
for(int i=;i<=n;i++){
int a;
scanf("%d",&a);
ve[a].push_back(i);//存该节点的子节点
}
dfs();
printf("%d\n",dp[]);
}
}

I - Nastya Is Buying Lunch

CodeForces - 1136D

题意:给你一个大小为n的排列好的数组,m对二元组(x,y),如果x在y前面且x和y相邻,则可以使x和y交换位置,问你最后一数最多能往前移动几步

思路:模拟交换过程。如果最后一个数能往前移,前面必定会有一个数和它有对应的二元组,因此找到那个区间,再模拟交换过程,查看是否能前移。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 401000
#define mod ((int)1e9+7)
int a[MAXN];
map<pair<int,int>,int> ma;
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=;i<n;i++)
scanf("%d",&a[i]);
for(int i=;i<m;i++){
int u,v;
scanf("%d %d",&u,&v);
ma[make_pair(u,v)]=;//标记所有能交换的二元组
}
int last=n-;
for(int i=n-;i>=;i--){//从倒数第二个数开始往前遍历
if(ma[make_pair(a[i],a[last])]){//如果存在一个数能与最后一个数交换,则模拟交换区间内的元素
int j;
for(j=i;j<last;j++){
if(ma[make_pair(a[j],a[j+])]){
swap(a[j],a[j+]);
}
else
break;
}
if(j==last){//每次移动成功的话,就把最后一个数向前移一位,避免继续遍历时遇到后面已经交换过的数。
last--;
}
}
}
printf("%d\n",n--last);
}

J - Easy billiards

ZOJ - 3761

题意:给你n个球的坐标,球可以朝{ 上,下,左,右 }中有另一个球的方向运动,并通过撞击另一个球使自己停下,被撞击的球沿着这个方向继续运动,如果这个方向上没有其他的球,被撞击的球将消失。

求最后最少能剩下几个球,并输出他们撞击的方向

思路:将可以互相撞击的球构成一棵树,从而变成了森林,最少剩下的球的数量就是树的数量,可以通过并查集求数量。(不用并查集也可以,先dfs,用vector存下撞击路径即可)

输出路径可以通过dfs,每次撞击都先由子节点撞击父节点

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 2010
#define MAXM 1000010
#define mod 998244353
int n, p[MAXN];
struct node {
int x, y;
}a[MAXN];
int find(int x) {
return p[x] == - ? x : p[x] = find(p[x]);
}
void join(int x, int y) {
int a = find(x), b = find(y);
if (a != b) {
p[a] = b;
}
}
int head[MAXN], v[MAXM], ne[MAXM];
int vis[MAXN];
int id;
void addEdge(int x, int y) {
v[++id] = y;
ne[id] = head[x];
head[x] = id;
} void dfs(int u, int fa) {
vis[u] = ;
for (int i = head[u]; i != -; i = ne[i])
{
int now = v[i];
if (!vis[now])
dfs(now, u);
}
if (fa != -)
{
printf("(%d, %d) ", a[u].x, a[u].y);
if (a[fa].x == a[u].x)
{
if (a[u].y < a[fa].y)
puts("UP");
else puts("DOWN");
}
else
{
if (a[u].x < a[fa].x) puts("RIGHT");
else puts("LEFT");
}
}
} int main() {
while (~scanf("%d", &n))
{
mm(p, -);
mm(head, -);
mm(vis, );
id = ;
for (int i = ; i < n; ++i)
scanf("%d%d", &a[i].x, &a[i].y);
for (int i = ; i < n; ++i)
{
for (int j = i + ; j < n; ++j)
{
if (a[i].x == a[j].x || a[i].y == a[j].y)
{
addEdge(i, j);
addEdge(j, i);
join(i, j);
}
}
}
//计算连通块数量
int ans = ;
for (int i = ; i < n; ++i)
if (p[i] == -) ans++;
printf("%d\n", ans);
for (int i = ; i < n; ++i)
{
if (p[i] == -) dfs(i, -);
}
}
}

K - What Kind of Friends Are You?

ZOJ - 3960

题意:有q个问题和n个询问,告诉你第i个问题那些人可以回答(1<=i<=q),然后第j个询问告诉你这个人能回答哪些问题,如果你能通过他回答的问题猜出他是谁,就输出他的名字,否则输出"Let's go to the  library!!"

思路:通过二进制保存每个人回答的问题,如果x能回答第i个问题,sum[x]+=1<<i

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 2010
#define MAXM 1000010
int n, q;
map<string, int>m;
map<int, string>ans; int main()
{
int t;
int k, x;
string s;
scanf("%d", &t);
map<string, int>::iterator it;
while (t--)
{
m.clear();
ans.clear();
scanf("%d%d", &n, &q);
scanf("%d", &k);
for (int i = ; i < k; ++i)
{
getchar();
cin >> s;
m[s] = ;
}
for (int i = ; i < q; ++i)
{
scanf("%d", &k);
while (k--)
{
getchar();
cin >> s;
m[s] += << i;
}
}
for (it = m.begin(); it != m.end(); it++)
{
if (ans.count(it->second))
ans[it->second] = "Let's go to the library!!";
else
ans[it->second] = it->first;
}
while (n--)
{
x = ;
for (int i = ; i < q; ++i)
{
scanf("%d", &k);
if(k) x += << i;
}
if (ans.count(x))
cout << ans[x] << endl;
else
cout << "Let's go to the library!!\n";
}
}
}

L - Skyscrapers

CodeForces - 1137A

题意:对于两条交叉的街道,可以改变街道上每个房子的高度,但是要维持同一条街道上房子之间的高矮性,即比他高的还是比他高,比他矮的还是比他矮,求这两条交叉的街道上更改高度后最高的房子的高度。给你n*m条交叉的街道,对于每个交叉点求出这两条交叉的街道上更改高度后最高的房子的高度。

思路:ans[i][j] = 1 + max(i街道上比交叉点矮的不同高度房子数,j街道上比交叉点矮的不同高度房子数)+max(i街道上比交叉点高的不同高度房子数,j街道上比交叉点高的不同高度房子数)

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
#define MAXN 1010
#define mod 998244353
int n, a[MAXN][MAXN], m;
int ma1[MAXN][MAXN], mi1[MAXN][MAXN];
int ma2[MAXN][MAXN], mi2[MAXN][MAXN];
vector<int>v;
int main()
{
scanf("%d%d", &n, &m);
for (int i = ; i < n; ++i)
{
for (int j = ; j < m; ++j)
scanf("%d", &a[i][j]);
}
for (int i = ; i < n; ++i)
{
v.clear();
for (int j = ; j < m; ++j)
v.push_back(a[i][j]);
sort(v.begin(), v.end());
int end = unique(v.begin(), v.end()) - v.begin();
for (int j = ; j < m; ++j)
{
mi1[i][j] = (int)(lower_bound(v.begin(), v.begin() + end, a[i][j]) - v.begin());
ma1[i][j] = end - mi1[i][j] - ;
}
}
for (int i = ; i < m; ++i)
{
v.clear();
for (int j = ; j < n; ++j)
v.push_back(a[j][i]);
sort(v.begin(), v.end());
int end = unique(v.begin(), v.end()) - v.begin();
for (int j = ; j < n; ++j)
{
mi2[j][i] = (int)(lower_bound(v.begin(), v.begin() + end, a[j][i]) - v.begin());
ma2[j][i] = end - mi2[j][i] - ;
}
}
for (int i = ; i < n; ++i)
{
for (int j = ; j < m; ++j)
printf("%d ", + max(mi1[i][j], mi2[i][j]) + max(ma1[i][j], ma2[i][j]));
printf("\n");
}
}

HZNU Training 4 for Zhejiang Provincial Collegiate Programming Contest 2019的更多相关文章

  1. HZNU Training 2 for Zhejiang Provincial Collegiate Programming Contest 2019

    赛后总结: T:今天下午参加了答辩比赛,没有给予队友很大的帮助.远程做题的时候发现队友在H上遇到了挫折,然后我就和她们说我看H吧,她们就开始做了另外两道题.今天一人一道题.最后我们在研究一道dp的时候 ...

  2. HZNU Training 1 for Zhejiang Provincial Collegiate Programming Contest

    赛后总结: TJ:今天我先到实验室,开始看题,一眼就看了一道防AK的题目,还居然觉得自己能做wwww.然后金姐和彭彭来了以后,我和他们讲了点题目.然后金姐开始搞dfs,我和彭彭看榜研究F题.想了很久脑 ...

  3. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Capture the Flag

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5503 The 12th Zhejiang Provincial ...

  4. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Team Formation

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5494 The 12th Zhejiang Provincial ...

  5. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Beauty of Array

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5496 The 12th Zhejiang Provincial ...

  6. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Lunch Time

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5499 The 12th Zhejiang Provincial ...

  7. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Convert QWERTY to Dvorak

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5502  The 12th Zhejiang Provincial ...

  8. zoj The 12th Zhejiang Provincial Collegiate Programming Contest May Day Holiday

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5500 The 12th Zhejiang Provincial ...

  9. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Demacia of the Ancients

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5504  The 12th Zhejiang Provincial ...

随机推荐

  1. Android Studio 蓝牙开发实例——基于Android 6.0

    因项目需要做一个Android 的蓝牙app来通过手机蓝牙传输数据以及控制飞行器,在此,我对这段时间里写的蓝牙app的代码进行知识梳理和出现错误的总结. 该应用的Compile Sdk Version ...

  2. UE4 坐标系 坐标轴旋转轴

    Pitch是围绕Y轴旋转,也叫做俯仰角. Yaw是围绕Z轴旋转,也叫偏航角. Roll是围绕X轴旋转,也叫翻滚角. UE4里,蓝图中的rotation的三个依次为roll,pitch,yaw.C++中 ...

  3. Gunicorn-Django部署

    1. 简单部署 1. sudo pip3 install gunicorn 2. cd 到django项目中 sudo python3 manage.py migrate 3.启动服务:sudo py ...

  4. 有助于提高"锁"性能的几点建议

    有助于提高"锁"性能的几点建议 1.减少锁持有时间 public synchronized void syncMethod() { othercode1(); mutextMeth ...

  5. Activiti 开发案例之动态指派任务

    流程图 以上是一个请假的流程图,以下为流程任务节点描述: 员工发起请假流程 部门经理审批 同意则进入人事审批 拒绝则调整申请或者直接结束流程 人事审批通过则进入销假环节 人事审批拒绝则调整申请或者直接 ...

  6. 控制台基于Quartz.Net组件实现定时任务调度(一)

    前言: 你曾经需要应用执行一个任务吗?比如现在有一个需求,需要每天在零点定时执行一些操作,那应该怎样操作呢? 这个时候,如果你和你的团队是用.NET编程的话,可以考虑使用Quartz.NET调度器.允 ...

  7. [Spring cloud 一步步实现广告系统] 17. 根据流量类型查询广告

    广告检索服务 功能介绍 媒体方(手机APP打开的展示广告,走在路上看到的大屏幕广告等等) 请求数据对象实现 从上图我们可以看出,在媒体方向我们的广告检索系统发起请求的时候,请求中会有很多的请求参数信息 ...

  8. Kafka集群配置---Windows版

    Kafka是一种高吞吐量的分布式发布订阅的消息队列系统,Kafka对消息进行保存时是通过tipic进行分组的.今天我们仅实现Kafka集群的配置.理论的抽空在聊 前言 最近研究kafka,发现网上很多 ...

  9. 在canvas中使用其他HTML元素

    做一个功能如下图,随机生成100个大小.颜色随机的小球.点击开始运动的时候,小球开始运动,然后点击停止运动的时候,小球停止运动. 点击旁边的白色或者黑色,则背景颜色变为相应的颜色. HTML部分: & ...

  10. Spring Boot Security Oauth2之客户端模式及密码模式实现

    Spring Boot Security Oauth2之客户端模式及密码模式实现 示例主要内容 1.多认证模式(密码模式.客户端模式) 2.token存到redis支持 3.资源保护 4.密码模式用户 ...