2019山东ACM省赛部分题解

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblems.do?contestId=1&pageNumber=32

A:

#include
using namespace std;

int main()
{
	int t;
	scanf("%d",&t);
	string a;
	long long y1,y2,m1,m2,d1,d2,ans;
	while(t--){
		scanf("%lld%lld%lld",&y1,&m1,&d1);
		cin>>a;
		scanf("%lld%lld%lld",&y2,&m2,&d2);
		ans=(y2-y1)*12*30+(m2-m1)*30+(d2-d1);
		if(a=="Monday")ans+=1;
		else if(a=="Tuesday")ans+=2;
		else if(a=="Wednesday")ans+=3;
		else if(a=="Thursday")ans+=4;
		else ans+=5;
		ans%=5;
		ans+=5;
		ans%=5;
		if(ans==0)printf("Friday\n");
		else if(ans==1)printf("Monday\n");
		else if(ans==2)printf("Tuesday\n");
		else if(ans==3)printf("Wednesday\n");
		else printf("Thursday\n");
	}
	return 0;
}

B:这个现场没做出来,赛后补的:https://blog.csdn.net/mmk27_word/article/details/90168671

C:第一思路是先把前n-1的算出来,然后在此基础上在进行一遍,求个最优,错了一发之后才想到,前n-1次可能对最后一次有负影响,所以在单独对一次取个最优即可

#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
char s[N];
int n,k;
int main()
{
	int T;
	ll xx,yy;
	ll ans;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&k);
		scanf("%s",s+1);
		xx=0,yy=0;
		ans=0;
		for(int i=1;i<=n;i++)
		{
			if(s[i]=='R') xx++;
			else if(s[i]=='L') xx--;
			else if(s[i]=='U') yy++;
			else yy--;
			ans=max(ans,abs(xx)+abs(yy));
		}
		
		xx=xx*(k-1);
		yy=yy*(k-1);
	//	ans=abs(xx)+abs(yy);
		for(int i=1;i<=n;i++)
		{
			if(s[i]=='R') xx++;
			else if(s[i]=='L') xx--;
			else if(s[i]=='U') yy++;
			else yy--;
			
			ans=max(ans,abs(xx)+abs(yy));
		}
		printf("%lld\n",ans);
	}
	return 0;
}

D:先判断一下是不是连通图,如果不是那就是s[0]赢了,若是那就是s[(m-(n-1))%k]的对立方赢

#include
using namespace std;
const int N=1e5+10;
struct node{
	int u,v;
}e[N];
char s[N];
int n,m,k;
int f[N];
int cnt;
void init()
{
	for(int i=0;i<=n;i++)
	{
		f[i]=i;
	}
	cnt=0;
}
int fath(int x)
{
	return x==f[x]?x:f[x]=fath(f[x]);
}
int main()
{
	int T;
	int x,y;
	int xx,yy;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&k);
		scanf("%s",s);
		scanf("%d%d",&n,&m);
		init();
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			xx=fath(x);
			yy=fath(y);
			if(xx==yy) continue;
			cnt++;
			f[xx]=yy;
		}
		if(cnt!=n-1)
		{
			printf("%c\n",s[0]);
		}
		else
		{
			m=m-(n-1);
			
			m=m%k;
			if(s[m]=='1')printf("2\n");
			else printf("1\n");
		}
	}
	return 0;
}

E:判断一下连续相同的两个数a1,a2之间有多少种数k,若摆放的容量大小大于等于k,那么a2就可以不用拿了,记录下每个位置的k,从小到大求下前缀和,也就是这些数量的位置的书是可以不用拿的,再用n减去即可。

#include
using namespace std;
const int N=1e5+100;
struct node{
	int l,r;
	int val;
}tree[N*40];
int n,a[N],vis[N];
int tot;
int root[N];
int build(int l,int r)
{
	int cur=++tot;
	tree[cur].val=0;
	tree[cur].l=tree[cur].r=0;
	if(l==r)
		return cur;
	int m=(l+r)>>1;
	tree[cur].l=build(l,m);
	tree[cur].r=build(m+1,r);
	return cur;
}
int update(int pos,int pre,int l,int r,int val)
{
	int cur=++tot;
	tree[cur]=tree[pre];
	tree[cur].val+=val;
	if(l==r) return cur;
	int mid=(l+r)>>1;
	if(pos<=mid) 
		tree[cur].l=update(pos,tree[pre].l,l,mid,val);
	else
		tree[cur].r=update(pos,tree[pre].r,mid+1,r,val);
	return cur; 
}
int query(int pos,int cur,int l,int r)
{
	if(l==r) return tree[cur].val;
	int mid=(l+r)>>1;
	if(pos<=mid) 
		return tree[tree[cur].r].val+query(pos,tree[cur].l,l,mid);
	else
		return query(pos,tree[cur].r,mid+1,r);
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		mapmp;
		tot=0;
		scanf("%d",&n);
		root[0]=build(1,n);
		for(int i=0;i<=n;i++)vis[i]=0;
		int tmp;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			if(mp[a[i]]==0)
			{
				root[i]=update(i,root[i-1],1,n,1);
			}
			else
			{
				tmp=update(mp[a[i]],root[i-1],1,n,-1);
				root[i]=update(i,tmp,1,n,1);
				
				vis[query(mp[a[i]],root[i],1,n)]++;
			}
			mp[a[i]]=i;
		}	
		for(int i=1;i<=n;i++)
		{
			vis[i]+=vis[i-1];
			printf("%d%c",n-vis[i]," \n"[i==n]);
		}
	}
	return 0;
}

F:

#include
using namespace std;
const int N=1e5+100;
long long a[N];
long long sum,ans;
int main()
{
	int t,n;
	scanf("%d",&t);
	while(t--){
		sum=0,ans=0;
		scanf("%d",&n);
		for(int i=0;i

H:队友搞的,题意我也不知道,后面再补上吧

#include
using namespace std;
const int N=1e5+100;
int t,n,now,ans;
struct node{
	int l,r;
}a[N];
bool cmp(const node &a,const node &b){
	return a.l,greater > q;
int i;
int main()
{
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(i=0;i=n)break;
				else
					now=a[i].l;
			}
			else{
				ans++;
				q.pop();
				now++;
			}
		}
		printf("%d\n",ans);	
	}
	return 0;
}

I:正向建边,求一定比每个数大的,反向建边求一下一定比每个数小的,若一个数一定比他大的和一定比他小的都小于n/2,那么这个数就符合条件,因为其他数既可以比他大也可以比他小

#include
using namespace std;
const int N=110;
struct node{
	int nex,to;
}e1[N*N],e2[N*N];
int head1[N],len1;
int head2[N],len2;
int n,m;
int in1[N],in2[N];
bitset<110> vis1[N],vis2[N];
void add1(int x,int y)
{
	e1[len1].to=y;
	e1[len1].nex=head1[x];
	head1[x]=len1++;
}
void add2(int x,int y)
{
	e2[len2].to=y;
	e2[len2].nex=head2[x];
	head2[x]=len2++;
}
struct node1{
	int id;
	bitset<110> pre;
	node1(){}
};
int main()
{
	int T;
	int x,y;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++)
		{
			head1[i]=-1;
			head2[i]=-1;
			in1[i]=0;
			in2[i]=0;
			for(int j=0;j<110;j++)
			{
				vis1[i][j]=0;
				vis2[i][j]=0;
			}
		}
		len1=0;
		len2=0;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			add1(x,y);
			add2(y,x);
			in1[y]++;
			in2[x]++;
		}
		queue q;
		node1 now,tmp;
		for(int i=1;i<=n;i++)
		{
			if(in1[i]==0)
			{
				tmp.id=i;
				tmp.pre=0;
				tmp.pre[i]=1;
				q.push(tmp);
			
			}
		}
		int cnt=0;
		int to;
		while(!q.empty())
		{
			now=q.front();q.pop();
			cnt++;
			for(int i=head1[now.id];i!=-1;i=e1[i].nex)
			{
				to=e1[i].to;
				in1[to]--;
				vis1[to]|=now.pre;
				if(in1[to]==0)
				{
					tmp.id=to;
					tmp.pre=0;
					tmp.pre=vis1[to];
					tmp.pre[to]=1;
					
					q.push(tmp);
				}
			}
		}
		if(cnt!=n)
		{
			for(int i=0;i

M:

#include
using namespace std;
int n,k;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&k);
		while(n>1 && k)
		{
			k--;
			n=(n+1)/2;
		}
		printf("%d\n",n);
	}
	return 0;
}

 

你可能感兴趣的:(整套题目)