codeforces Round#158 Div.2 小结

Codeforces Round # 158 (Div.2)

    这次练习我有很大的收获。首先简单的题目不能想复杂了,像第一题,n=8,这个条件被我无视了;其次简单的贪心题目出了点问题,以后思维要更严密;然后c++的stl库用起来真的很方便。总之花了一天的时间把这套题AC了。

A Adding Digits

题目大意:定义操作(a,b)::在a后面添加一个数字(10进制),并使新的数字能整除b;求a,b执行操作(a,b)n次之后a的值。

思路:第一次操作之后添加0就可以了。

# include <iostream>
# include <cstdio>
using namespace std;


int a,b,n;
int main()
{
	scanf("%d%d%d",&a,&b,&n);
	int t=(b-(a*10%b))%b;
	if(t<10)
	{
		printf("%d%d",a,t);
		--n;while(n--)printf("0");
	}
	else printf("-1\n");
	return 0;
}

B Ancient Prophesy

题目大意:给一个字符串,如果一个连续字串满足"dd-mm-yyyy"的日期格式且年份在2013~2015之间,则为合法日期,出现次数最多的合法日期。

思路:可以直接模拟,用map统计;我写了个自动机,感觉用起来很方便,常数上较小。

# include <iostream>
# include <cstdio>
using namespace std;

const int C[11][2]={{1,0},{2,0},{2,3},{4,0},{5,0},{2,6},{7,0},{8,0},{9,6},{10,3},{2,3}};
const int Day[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int HASH[3][12][31],D[1200],Cnt,Ans,w;
char a[120000], ans[1200][11];

void pushdata(const char *p)
{
	static int dd,mm,yy;
	static int *temp;
	if(*(p+6)!='2' || *(p+7)!='0' || *(p+8)!='1')return;
	
	dd=10*(*(p+0)-'0')+(*(p+1)-'0');
	mm=10*(*(p+3)-'0')+(*(p+4)-'0');
	yy=2010+(*(p+9)-'0');
	if(yy<2013 || yy>2015)return;
	if(mm<1 || mm>12)return;
	if(dd<1 || dd>Day[mm-1])return;
	
	temp=&HASH[yy-2013][mm-1][dd-1];
	if(*temp==0)*temp=++Cnt,sprintf(ans[Cnt],"%02d-%02d-%d",dd,mm,yy);
	D[*temp]++;
}
int main()
{
	scanf("%s",a);
	for(int i=0;a[i];i++)
	{
		w=C[w][(a[i]=='-')];
		if(w==10)pushdata(a+(i-9));
	}

	Ans=1;
	for(int i=2;i<=Cnt;i++)
		if(D[i]>D[Ans])Ans=i;
	printf("%s\n",ans[Ans]);
}

C Balls and Boxes

题目大意:有N个盒子,每个里面有一些小球;出题人将一个盒子中的小球全部拿出,然后从下一个开始挨个发球,直到发完为止,第N个的下一个是第1个这样循环;现在已知操作后每个盒子中球的数量和最后一个球发到那个盒子,求操作前盒子里的球数。

思路:通过数学方法推导,可以发现找最少的盒子就可以了,所以直接模拟,注意一些细节。


# include <iostream>
# include <cstdio>
# define For(i,a,b) for(int i=a;i<=b;i++)
# define rep(i,n) For(i,1,n)
using namespace std;
long long a[100010],m=~0U>>1;
int n,x;

int getint()
{
	static char c; 
	static int ret;
	while(!isdigit(c=getchar()));
	ret=c-'0';
	while( isdigit(c=getchar()))
		ret=ret*10+c-'0';
	return ret;
}
inline void write()
{
	rep(i,n)printf("%lld ",a[i]);printf("\n");
}
int main()
{
	n=getint(); x=getint();
	rep(i,n) a[i]=getint();
	rep(i,n) if(a[i]<m)m=a[i];
	if(a[x]==m){rep(i,n)a[i]-=m;a[x]=m*n;write();return 0;}
	for(int i=x;i;--i)if(a[i]==m){
		rep(j,n)a[j]-=m;For(j,i+1,x)a[j]--;a[i]=m*n+x-i;write();return 0;
	}
	for(int i=n;i;--i)if(a[i]==m){
		rep(j,n)a[j]-=m+1;For(j,x+1,i)a[j]++;a[i]=(m+1)*n-(i-x);write();return 0;
	}
}

D Black and White Tree

题目大意:一棵树黑白染色,知道每个节点染色情况以及每个节点连出边的权值和;求原图(输出所有边和边权)

思路:保证一定有解,限制又很少,所以直接贪心构造即可。


# include <iostream>
# include <cstdio>
# include <vector>
# include <algorithm>

using namespace std;

#define mp make_pair
#define f first
#define s second

vector<pair<int,int> >v[2];
int main()
{
	int n,i,j,k,t;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%d%d",&t,&k),
		v[t].push_back(mp(k,i));
	sort(v[0].begin(),v[0].end());
	sort(v[1].begin(),v[1].end());
	for(i=j=0;i<v[0].size()&&j<v[1].size();)
	{
		k=min(v[0][i].f,v[1][j].f);
		printf("%d %d %d\n",v[0][i].s,v[1][j].s,k);
		v[0][i].f-=k,v[1][j].f-=k;
		
		if(v[0][i].f)j++; else
		if(v[1][j].f)i++; else
		(i+1<v[0].size())?i++:j++;
	}
	return 0;
}


E Dividing Kingdom

题目大意:平面上有一堆点,两横两竖四条直线分点集为九部分,给定每部分的点个数,球直线。

大致思路:枚举所有点,O(1)求出直线,然后用线段树判断。O(9!*log n*log n)

# include <iostream>
# include <cstdio>
# include <vector>
# include <algorithm>
using namespace std;

const int inf=~0U>>1;
const int N=100010;
#define M tree[u]
#define ML tree[u<<1]
#define MR tree[u<<1|1]

pair<int,int>p[N],q[N];
vector<int>C(9),e;

struct Seg{
	struct node{
		int l,r;
		vector<int>co;
	}tree[N<<2];
	void init(int u,int l,int r,int L,int R){
		M.l=l,M.r=r;
		int mid=(l+r)>>1,pp;
		for(int i=L;i<=R;i++){
			M.co.push_back(p[i].second);
			if(p[i].first<=e[mid])pp=i;
		}
		sort(M.co.begin(),M.co.end());
		if(l==r)return;
		init(u<<1,l,mid,L,pp);
		init(u<<1|1,mid+1,r,pp+1,R);
	}
	int query(int u,int x,int y){
		if(e[M.r]<=x)
			return upper_bound(M.co.begin(),M.co.end(),y)-M.co.begin();
		int ret=query(u<<1,x,y);
		if(e[MR.l]<=x) ret+=query(u<<1|1,x,y);
		return ret;
	}
}seg;

bool solve()
{
	static int x,xx,y,yy,a,b,c,d;
	a=C[0]+C[3]+C[6],b=a+C[1]+C[4]+C[7];
	x=p[a-1].first,xx=p[b-1].first;
	if(p[a].first==x||p[b].first==xx)return 0;
	c=C[0]+C[1]+C[2],d=c+C[3]+C[4]+C[5];
	y=q[c-1].first,yy=q[d-1].first;
	if(q[c].first==y||q[d].first==yy)return 0;
	if(seg.query(1,x,y)!=C[0])return 0;
	if(seg.query(1,xx,y)!=C[0]+C[1])return 0;
	if(seg.query(1,x,yy)!=C[0]+C[3])return 0;
	if(seg.query(1,xx,yy)!=C[0]+C[1]+C[3]+C[4])return 0;
	printf("%lf %lf\n%lf %lf\n",x+0.5,xx+0.5,y+0.5,yy+0.5);
	return true;
}

int main()
{
	int n,x,y; scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d%d",&x,&y);
		p[i]=make_pair(x,y);
		q[i]=make_pair(y,x);
		e.push_back(x);
	}
	sort(e.begin(),e.end());
	e.erase(unique(e.begin(),e.end()),e.end());
	sort(p,p+n); sort(q,q+n);
	seg.init(1,0,e.size()-1,0,n-1);
	for(int i=0;i<9;i++)scanf("%d",&x),C[i]=x;
	sort(C.begin(),C.end());
	
	bool flag=false;
	do{
		flag=solve();
		if(flag)break;
	}while(next_permutation(C.begin(),C.end()));
	if(!flag)printf("-1\n");
	return 0;
}

P.S :这个stl真方便啊,二分查找,排列组合,去除多余项,排序什么的竟然都有!!用pascal的真心吃亏。。。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值