VK Cup 2016 round 2题解

VK CUP 2016 round 2
Div2 :

A:直接1,2,1,2的送,答案就是n / 3 * 2 + (n % 3 != 0)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n;
int main() {
	cin>>n;
	cout<<n / 3 * 2 + (n % 3 != 0);
}

B:按照原图中的箭头跳,跳出了就是false,如果跳到了以前访问的点就是true.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,A[100010];
bool visit[100010];
char s[100010];
int main() {
	//freopen("lx.in","r",stdin);
	cin>>n;
	scanf("%s",s + 1);
	for(int i = 1;i <= n;i ++) scanf("%d",&A[i]);
	int x = 1;
	memset(visit,false,sizeof(visit));
	while(1)
	{
		if(visit[x]) {printf("INFINITE");return 0;}
		visit[x] = true;
		if(s[x] == '>') 
		{
			x = x + A[x];
			if(x <= 0 || x > n) {printf("FINITE");return 0;} 
		}
		else 
		{
			x = x - A[x];
			if(x <= 0 || x > n) {printf("FINITE");return 0;}
		}
	}
}

Div2 C & Div1 A : 

    按照题意暴力模拟,f[i][j]表示i行j列实际表示的是原来矩阵的哪一个数.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,m,q,a,b,c,father[110][110],Ans[110][110],op;
int main() {
	//freopen("lx.in","r",stdin);
	scanf("%d%d%d",&n,&m,&q);
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= m;j ++)
			father[i][j] = (i - 1) * m + j;
	for(int i = 1;i <= q;i ++)
	{
		scanf("%d",&op);
		if(op == 1) 
		{
			scanf("%d",&a);
			int t = father[a][1];
			for(int j = 1;j < m;j ++)
				father[a][j] = father[a][j + 1];
			father[a][m] = t;
		}
		if(op == 2)
		{
			scanf("%d",&a);
			int t = father[1][a];
			for(int j = 1;j < n;j ++)
				father[j][a] = father[j + 1][a];
			father[n][a] = t;
		}
		if(op == 3)
		{
			scanf("%d%d%d",&a,&b,&c);
			int t = father[a][b];
			int x = (t - 1) / m + 1;
			int y = t - (x - 1) * m;
			Ans[x][y] = c;
		}
	}
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1;j <= m;j ++)
		{
			cout<<Ans[i][j]<<' ';
		}
		cout<<endl;
	}
}

Div2 D & Div1 B :

    分析一下发现奇数的男生的移动是相似的,偶数之间也是相似的,所以只用分别算出奇数和偶数分别移动了多少就可以了.(注意中途爆int.T_T)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,q,A[2000010],B[2000010],Ans[1000010],step;
int main() {
	scanf("%d%d",&n,&q);
	for(int i = 1;i <= q;i ++)
	{
		scanf("%d",&A[i]);
		if(A[i] == 1) scanf("%d",&B[i]);
	}
	step = 0;
	for(int i = 1;i <= q;i ++)
	{
		if(A[i] == 1) step = ((step + B[i]) % n + n) % n;
		else if((step + 1) % 2 == 0) step = ((step - 1) % n + n) % n;
		else step = ((step + 1) % n + n) % n;
	}
	for(int i = 1;i <= n;i += 2)
		Ans[(((i + step) % n) + n) % n] = i;
	step = 0;
	step = 0;
	for(int i = 1;i <= q;i ++)
	{
		if(A[i] == 1) step = ((step + B[i]) % n + n) % n;
		else if((step) % 2 == 0) step = ((step - 1) % n + n) % n;
		else step = ((step + 1) % n + n) % n;
	}
	for(int i = 2;i <= n;i += 2)
		Ans[(((i + step) % n) + n) % n] = i;
	Ans[n] = Ans[0];
	for(int i = 1;i <= n;i ++)
		printf("%d ",Ans[i]);
}

Div1 C :

    设Max[i] = max(a,b) <= i,Min[i] = min(a,b) >= i,s[i] = pa[1] + pa[2] +...pa[i],t[i] = pb[1] + pb[2] +..退一下公式发现s[i] * t[i] = Max[i],1 - s[i] - t[i] + s[i] * t[i] = Min[i + 1],解一下每个方程就可以了,注意sqrt()里面的数要和0取max...

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
#define g(a) a<0?-a:a
using namespace std;
int n;
double Max[100010],Min[100010],s[100010],t[100010];
int main() {
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++) scanf("%lf",&Max[i]);
	for(int i = 1;i <= n;i ++) scanf("%lf",&Min[i]);
	for(int i = 1;i <= n;i ++) Max[i] += Max[i - 1];
	for(int i = n;i >= 1;i --) Min[i] += Min[i + 1];
	for(int i = 1;i <= n;i ++)
	{
		double val = 1.0 - Min[i + 1] + Max[i];
		double delta = val * val - 4.0 * Max[i];
		s[i] = (val + sqrt(g(delta))) / 2.0;
		t[i] = val - s[i];
	}
	for(int i = 1;i <= n;i ++) printf("%0.10f ",s[i] - s[i - 1]);
	cout<<endl;
	for(int i = 1;i <= n;i ++) printf("%0.10f ",t[i] - t[i - 1]);
	return 0; 
}

Div2 E & Div1 D :

    按照询问的数排序,那么对于一段连续的询问其实询问的都是一个数,那么区间线段树加加减减就可以了.

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node {int v;int t;int op;int id;}; node A[1000010];
int tot,v[1000010],flag[8000010],val[8000010],n,Ans[1000010];
bool comp(const node &x,const node &y) {
	if(x.v != y.v) return x.v < y.v;
	return x.id < y.id;
}
int hash(int x) {
	int head = 1,tail = tot,ret;
	while(head <= tail)
	{
		int Mid = (head + tail) >> 1;
		if(v[Mid] <= x) ret = Mid,head = Mid + 1;
		else tail = Mid - 1;
	}
	return ret;
}
void Add(int Now,int l,int r,int x,int y,int z,int w) {
	if(l >= x && r <= y)
	{
		if(flag[Now] != z && flag[Now] != 0)
		{
			flag[Now] = z;
			val[Now] = w;
		}
		else flag[Now] = z,val[Now] += w;
		return ;
	}
	int Mid = (l + r) >> 1;
	if(x <= Mid) Add(Now << 1,l,Mid,x,y,z,w);
	if(y > Mid) Add(Now << 1 | 1,Mid + 1,r,x,y,z,w); 
}
int Ask(int Now,int l,int r,int x,int y) {
	if(l == r)
	{
		if(flag[Now] == y) return val[Now];
		return 0;
	}
	int Mid = (l + r) >> 1,ret = 0;
	if(flag[Now] == y) ret += val[Now]; 
	if(x <= Mid) return ret + Ask(Now << 1,l,Mid,x,y);
	else return ret + Ask(Now << 1 | 1,Mid + 1,r,x,y);
}
int main() {
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++)
	{
		scanf("%d%d%d",&A[i].op,&A[i].t,&A[i].v);
		v[ ++tot] = A[i].t;A[i].id = i;
	}
	sort(v + 1,v + tot + 1);
	for(int i = 1;i <= n;i ++)
		A[i].t = hash(A[i].t);
	sort(A + 1,A + n + 1,comp);
	for(int i = 1;i <= n;i ++) Ans[i] = -1;
	for(int i = 1;i <= n;i ++)
	{
		if(A[i].op == 1)
			Add(1,1,n,A[i].t,n,A[i].v,1);
		if(A[i].op == 2)
			Add(1,1,n,A[i].t,n,A[i].v,-1);
		if(A[i].op == 3)
			Ans[A[i].id] = Ask(1,1,n,A[i].t,A[i].v);
	}
	for(int i = 1;i <= n;i ++)
		if(Ans[i] != -1)
			printf("%d\n",Ans[i]);
	return 0; 
}

然而Div1 E,F出题人都没写题解...(我就这两道做不来结果他就没写题解啊啊啊啊...)









你可能感兴趣的:(VK Cup 2016 round 2题解)