2018.9.16考试总结

版权声明:转载记得声明噢! https://blog.csdn.net/Richard__Luan/article/details/82776774

今天的题是真的沙雕
第一题

【题目描述】
Yashem66学长有严重的强迫症!他完全无法忍受那些令他抓狂的东西,比如文具袋里的直尺,比如画得不规范的立方体。他总是自言自语:强人♂所难。
请写出一个程序,程序在读入立方体的三个棱长后,输出一个格式如样例的“立方体”。
【输入】
每个测试点一组测试数据,每组数据包含三个数字,表示立方体的长、宽、高分别为a,b,c。
【输出】
输出一个规定尺寸的立方体(形式如样例)。
加号减号放一块就变成正负号了。。
【数据范围与约定】
对于100%的数据满足 — a,b,c<=20
(提示)把样例复制到记事本里用等宽字体看体验更佳。
这题恶心模拟。。
Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int a,b,c;
char s[505][505];
int main()
{
	memset(s,' ',sizeof(s));
	scanf("%d%d%d",&a,&b,&c);	
	int n=2*b+2*c+1;
	int m=2*b+2*a+1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
		if(i+j<=2*b+1||(n-i+1)+(m-j+1)<=2*b+1)s[i][j]='.';	
		else 
		if(i%2==0)
		{
			if(i<=2*b)
			{
				if(j%2==0)s[i][j]='/';
				else if(i/2>=(m-j+2)/2)s[i][j]='|';
				else s[i][j]='.';
			}	
			else 
			{
				if(j&1)s[i][j]='|';
				else if((m-j+1)/2<=b)s[i][j]='/';
				else s[i][j]='.';
			}	
		}
		}
	}

	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
		if(s[i][j]!=' ')continue;
		if(i<=2*b)
		{
			if(j&1)s[i][j]='+';
			else 
			{
			if(s[i+1][j-1]=='|')s[i][j]='.';
			else 
			{
			s[i][j]='-';
			}
			}
		}
		else if(s[i-1][j]=='/'&&s[i+1][j]=='/')
		{
			if(s[i+1][j-1]=='|')s[i][j]='.';
			else 
			{
			s[i][j]='-';
			}
		}
		else 
		{
			if(j&1)s[i][j]='+';
			else s[i][j]='-';
		}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("%c",s[i][j]);
		}
		printf("\n");
	}
	return 0;
}

第二题

【题目描述】
Yashem66学长喜欢数独和妹子。在基友们的疯狂安利下,学长又入了16 * 16数独的大坑,对妹子日渐冷淡。而妹子不甘示弱、争风吃醋,于是便把学长做好的16 * 16数独分割成了4 * 4的16个方块后(数独术语中又称之为宫),进行如下操作若干次:任选一个宫后,使其逆时针旋转90°(一个宫可被旋转任意次)。
学长看着被搞坏的数独陷入了沉思:她至少要操作多少次呢?
【输入】
每个测试点多组测试数据,第一行一个整数T,表示共有T组测试数据。
对于每组测试数据,输入一个被学姐玩坏的16 * 16的数独,数独内元素以16进制数(既0123456789ABCDEF)表示。
【输出】
对于每组数据输出一行,表示学姐至少操作了多少次
【样例】
Input:
1
681D5A0C9FDBB2F7
0A734B62E167D9E5
5C9B73EF3C208410
F24ED18948A5CA63
39FAED5616400B74
D120C4B7CA3DEF38
7EC829A085BE6D51
B56438F129F79C2A
5C7FBC4E3D08719F
AE8B1673BF42A58D
60D3AF25619C30BE
294190D8EA57264C
C7D1B35606835EAB
AF52A1E019BE4306
8B36DC78D425F7C9
E409492FC7FA18D2
Output:
5

【数据范围与约定】
对于10%的数据满足 — T<=1,000
对于20%的数据满足 — T<=5,000
对于60%的数据满足 — T<=15,000
对于100%的数据满足 — T<=35,000

搜索。我们把每一行可能的状态列举出来,四进制,0表示不旋转,1表示转一次,以此类推
然后判断合不合法位运算就好了
具体看代码
Code

#include <bits/stdc++.h>
using namespace std;
 
inline char get_val(char ch) {
    if('0'<=ch && ch<='9') return ch-'0';
    return 10+ch-'A';
}
inline int add(int a,int b) {
    if(a+b<4) return a+b;
    return a+b-4;
}
 
#define bit(k) (1<<(k))
const int n=16;
int T;
char s[n+5][n+5];
int grid[n+5][n+5][4];
int rot[n+5][n+5], ROT[n+5];
 
void init() {
    register int i,j,k;
    for(i=0;i<n;++i) {
        ROT[i]=0;
        for(j=0;j<n;++j) {
            rot[i][j]=0;
            for(k=0;k<4;++k)
                grid[i][j][k]=0;
        }
    }
    return;
}
 
void calc_grid(int x,int y) {
    register int i,j;
    for(i=x*4;i<(x+1)*4;++i)
    for(j=y*4;j<(y+1)*4;++j) {
        if(i==4*x) grid[x][y][0]|=bit(s[i][j]);
        if(j==4*y) grid[x][y][1]|=bit(s[i][j]);
        if(i==4*x+3) grid[x][y][2]|=bit(s[i][j]);
        if(j==4*y+3) grid[x][y][3]|=bit(s[i][j]);
    }
    return;
}
 
bool check_row(int r) {
    int cur1=0;
    for(int j=0;j<4;++j) cur1|=grid[r][j][rot[r][j]];
    return (cur1==((1<<16)-1));
}
 
bool dfs_row(int x,int y) {
    if(y==4) return check_row(x);
    for(int i=0;i<4;++i) {
        rot[x][y]=i;
        if(dfs_row(x,y+1)) return true;
    }
    return false;
}
 
bool check_col(int c) {
    int cur=0;
    for(int i=0;i<4;++i) cur|=grid[i][c][(rot[i][c]+ROT[i]+1)%4];
    return (cur==((1<<16)-1));
}
 
bool dfs_col(int x,int y) {
    if(x==4) return check_col(y);
    for(int i=0;i<4;i+=2) {
        ROT[x]=i;
        if(dfs_col(x+1,y)) return true;
    }
    return false;
}
 
void work() {
    register int i,j;
    init();
    for(i=0;i<n;++i) {
        scanf("%s",s[i]);
        for(j=0;j<n;++j)
            s[i][j]=get_val(s[i][j]);
    }
 
    for(i=0;i<4;++i)
        for(j=0;j<4;++j)
            calc_grid(i,j);
 
    for(i=0;i<4;++i)
        dfs_row(i,0);
    dfs_col(0,0);
 
    for(i=0;i<4;++i) if(ROT[i])
        for(j=0;j<4;++j)
            rot[i][j]+=ROT[i];
 
    int ans1=0;
    for(i=0;i<4;++i)
        for(j=0;j<4;++j)
            ans1+=rot[i][j]%4;
    int ans2=0;
    for(i=0;i<4;++i)
        for(j=0;j<4;++j)
            ans2+=(rot[i][j]+2)%4;
 
    printf("%d\n",min(ans1,ans2));
    return;
}
 
int main() {
 
    for(scanf("%d",&T);T;T--)
        work();
 
    return 0;
}

第三题

【题目描述】
Yashem66学长作为第五期团的成员踏上了新大陆。第五期团共有n个成员,分布在大陆各处,每个成员都分别开拓了一条通往五期团其他成员位置的双向路径,且保证任何两个成员间都可互相到达。熔山龙对地脉的反复冲击使地貌变得多变,每条路径有一个初始崎岖度wei,熔山龙的冲击很可能会改变路径的崎岖度。由于学长的肝爆了,作为学长的搭档,团长交给你了一些你力所能及的任务,任务中可能是两种操作之一:
1)0 id val,将第id条路径的崎岖度改为val;
2)1 x y,询问x与y之间的崎岖度最小的路线的崎岖度(路线的崎岖度为路线上各路径的崎岖度之和)。
【输入】
输入数据的第一行包括两个整数n、m ,分别表示五期团的人数和任务的数目;接下来的n行,每行三个整数u、v、wei,表示有一条崎岖度为wei的从u到v的路径;接下来的m行,每行三个整数op、x、y,描述任务的内容。
【输出】
对于每个op=1的任务,输出一行一个整数作为答案。
【样例1】
Input1:
5 5
1 2 3
2 3 5
2 4 5
2 5 1
4 3 3
0 1 5
1 3 2
1 5 4
0 5 4
1 5 1
Output1:
5
6
6
【样例2】
Input2:
5 3
1 2 3
1 3 2
3 4 4
4 5 5
2 5 5
0 1 3
0 4 1
1 1 4
Output2:
6
【数据范围与约定】
对于40%的数据满足 — n,m<=1,000
对于100%的数据满足 — n,m<=200,000 , 路径权值<=100,000

裸基环树剖,代码长度6k
考场上三个半点都给你也打不完。。
等等!貌似这道题可以用更简单的方法解决
我们来一个dfs序,用树状数组维护就好了~
还是
具体看代码
Code

#include<cstdio>
#include<iostream>
#define lowbit(x) x&(-x)
using namespace std;
int n,m;
int f[2000005];
int fst[2000005];
int nxt[4000005];
int k[4000005];
int v[4000005];
int edge;
void add(int x,int y,int val)
{
	edge++;
	nxt[edge]=fst[x];
	fst[x]=edge;
	v[edge]=y;
	k[edge]=val;
}
inline int find(int x)
{
	return f[x]=(f[x]==x?x:find(f[x]));
}
int xx[2000005];
int yy[2000005];
int ww[2000005];
int deep[2000005];
int dfn[2000005];
int tt[2000005];
int fa[300005][30];
int cnt;
long long sum[2000005];
void ad(int x,int val)
{
	while(x<=n)
	{
		sum[x]+=val;
		x+=lowbit(x);
	}
}
long long query(int x)
{
	long long ans=0;
	while(x)
	{
		ans+=sum[x];
		x-=lowbit(x);
	}
	return ans;
}
void dfs(int x,int pre,int val)
{
	dfn[x]=++cnt;
	fa[x][0]=pre;
	deep[x]=deep[pre]+1;
	ad(cnt,val);
	for(int i=fst[x];i;i=nxt[i])
	{
		//cout<<x<<" "<<v[i]<<" "<<pre<<endl;
		if(v[i]==pre)continue;
		else 
		{
		dfs(v[i],x,k[i]);	
		}
	}
	tt[x]=cnt;
	ad(cnt+1,-val);
}
int lca(int x,int y)
{
	if(deep[x]<deep[y])swap(x,y);
	for(int i=25;i>=0;i--)
	{
		if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
	}
	if(x==y)return x;
	for(int i=25;i>=0;i--)
	{
		if(fa[x][i]!=fa[y][i])
		{
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return fa[x][0];
}
long long dist(int x,int y)
{
	int vv=lca(x,y);
	return query(dfn[x])+query(dfn[y])-2*query(dfn[vv]);
}
int main()
{


	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		f[i]=i;
	}
	int ll,rr,vl,id;
	for(int i=1;i<=n;i++)
	{
		int x,y,val;
		scanf("%d%d%d",&x,&y,&val);
		int fx=find(x);
		int fy=find(y);
		if(fx==fy)
		{
			ll=x;
			rr=y;
			vl=val;
			id=i;
		}
		else
		{
			add(x,y,val);
			add(y,x,val);
			f[fx]=fy;
		}
		xx[i]=x;
		yy[i]=y;
		ww[i]=val;
	}
	dfs(1,0,0);
	for(int j=1;j<=25;j++)
	{
		for(int i=1;i<=n;i++)
		{
		fa[i][j]=fa[fa[i][j-1]][j-1];	
		}
	}
	for(int i=1;i<=m;i++)
	{
		int op,y,x;
		scanf("%d%d%d",&op,&x,&y);
		if(op==0)
		{
			if(id==x)vl=y;
			else
			{
				int u=(fa[xx[x]][0]==yy[x]?xx[x]:yy[x]);
				ad(dfn[u],-ww[x]+y);
				ad(tt[u]+1,-y+ww[x]);
				ww[x]=y;
			}
		}
		else
		{
			long long ans=dist(x,y);
			ans=min(ans,dist(x,ll)+dist(y,rr)+vl);
			ans=min(ans,dist(x,rr)+dist(y,ll)+vl);
			printf("%lld\n",ans);
		}
	}
	return 0;
}

顺便吐槽一下,沙雕出题人直接从hdu扒题,样例都一样,无语。。

猜你喜欢

转载自blog.csdn.net/Richard__Luan/article/details/82776774