Codeforces Round #207 (Div. 1)

A:

我是用最拙计的方法套线段树过的。倒过来更新,每次用x覆盖掉区间[l,x-1] [x+1,r],初始全0。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
  
/*-------------------------Template----*/
#define N  300010 
#define E  50000
#define ll long long
#define CUBE(x) ((x)*(x)*(x))
#define SQ(x)     ((x)*(x))
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define maxAry(a,n) max_element(a,a+(n))
#define minAry(a,n) min_element(a,a+(n))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int PRIME =999983;
const int MOD   =10007;
const int MULTI =1000000007;
const double EPS=1e-9;
/*----------------------end Template----*/

class segTree{
#define lson rt<<1
#define rson rt<<1|1
#define rtl seg[rt].l
#define rtr seg[rt].r
private:
	struct segment{
		int l,r,who,mark;
    }seg[N<<2];
public:
	void pushdown(int rt)
	{
		if(seg[rt].mark==0) return ;
		seg[lson].who=seg[rt].mark;
		seg[rson].who=seg[rt].mark;
		seg[lson].mark=seg[rt].mark;
		seg[rson].mark=seg[rt].mark;
		seg[rt].mark=0;
	}
	void update(int who,int L,int R,int rt)
	{
		if(L<=rtl && rtr <=R){
			seg[rt].who=who;
			seg[rt].mark=who;
			return ;
		}
		pushdown(rt);
		int mid=(rtl+rtr)>>1;
		if(L<=mid) update(who,L,R,lson);
		if(R>mid) update(who,L,R,rson);
	}
	void output(int rt)
	{
		if(rtl==rtr){
			printf("%d ", seg[rt].who);
			return ;
		}
		pushdown(rt);
		output(lson);
		output(rson);
	}
	void build(int l,int r,int rt)
	{
		rtl=l,rtr=r;
		seg[rt].who=0;
		seg[rt].mark=0;
		if(l==r) return ;
		int mid=(l+r)>>1;
		build(l,mid,lson);
		build(mid+1,r,rson);
	}
}T;

int l[N],r[N],x[N];

int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	T.build(1,n,1);
	for(int i=0;i<m;i++)
		scanf("%d%d%d",&l[i],&r[i],&x[i]);
	for(int i=m-1;i>=0;i--){
		if(x[i]>l[i])
			T.update(x[i],l[i],x[i]-1,1);
		if(x[i]<r[i])
			T.update(x[i],x[i]+1,r[i],1);
	}
	T.output(1);
	puts("");
	return 0;
}



B:

         我们考虑如果length(A) 与 length(B) 互质(以下记为al,bl)。那么不断复制它们,会出现循环周期,一个周期的长度是al*bl。

         在一个周期内,A中任一字符都会和B中所有字符配对一次。如果al与bl不互质的话,我们可以求出最大公约数g。因为al/g和bl/g是互质的,那么我们就可以以g为单位长度来划分A,B,使其分成al/g段和bl/g段。这样A中任一段都会和B中所有段配对一次。

         得出这个结论之后,我们就统计一下cnt[i%g][A[i]-'a'],对于B也统计一下,然后乘一下就是A[i]==B[i]的数量。不过只是(al/g)*(bl/g)*g长度内的,所以还要乘以n*al/((al/g)*(bl/g)*g),化简下就是n*g/bl。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
  
/*-------------------------Template----*/
#define N  1000010 
#define E  50000
#define ll long long
#define CUBE(x) ((x)*(x)*(x))
#define SQ(x)     ((x)*(x))
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define maxAry(a,n) max_element(a,a+(n))
#define minAry(a,n) min_element(a,a+(n))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int PRIME =999983;
const int MOD   =10007;
const int MULTI =1000000007;
const double EPS=1e-9;
/*----------------------end Template----*/

char a[N],b[N];
int cnt[N][26],cb[N][26];

int gcd(int a,int b){ return b?gcd(b,a%b):a; }

int main()
{	
	ll n,m,al,bl,same=0;
	scanf("%I64d%I64d",&n,&m);
	scanf("%s%s",a,b);
	al=strlen(a);
	bl=strlen(b);
	int g=gcd(al,bl);
	for(int i=0;i<al;i++) cnt[i%g][a[i]-'a']++;
	for(int i=0;i<bl;i++) same+=cnt[i%g][b[i]-'a'];
	same*=n/(bl/g);
	printf("%I64d\n", n*al-same);
	return 0;
}


C:

贪心,很多贪法都能过,就是容易FST。我的做法是优先把2变成3,变成4的话消耗太多,可能最后不够的话还要再变回3。所以排序一下,0的忽略,然后把前面的拿到后面,使得后面的都变成3。这样最后只会剩下一个数是小于3的(忽略0),因为2 2会成为 1 3, 1 1会成为 0 2, 1 2会成为0 3,都是剩一个数小于3。然后再看最后这个数怎么调整,有两种策略,一种是把它分配到数值是3的位置,还一种是把4拿出1来,补足3。对于第一种策略,还需要注意一下细节。就是如果这个数比原来的小,说明它前面有别的人换进来,而我们现在的策略是把当前的人都分配到3的地方,那之前换进来的人可以认为直接分配到了3的地方,这样不需要再花费代价。在两种策略中取下最小。如果两种策略都无法操作,那就输出-1。


code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
  
/*-------------------------Template----*/
#define N  1000010 
#define E  50000
#define ll long long
#define CUBE(x) ((x)*(x)*(x))
#define SQ(x)     ((x)*(x))
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define maxAry(a,n) max_element(a,a+(n))
#define minAry(a,n) min_element(a,a+(n))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int PRIME =999983;
const int MOD   =10007;
const int MULTI =1000000007;
const double EPS=1e-9;
/*----------------------end Template----*/

int a[N],d[N];

int main()
{	
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&a[i]),d[i]=a[i];
	sort(a,a+n);
	sort(d,d+n);
//	for(int i=0;i<n;i++) printf("%d ", a[i]); puts("");
	int m=upper_bound(a,a+n,2)-a;
	int ans=0;
	for(int i=0,j=m-1;i<j;i++){
		if(a[i]==0) continue;
		if(++a[j]==3) j--;
		if(--a[i]) i--;
		ans++;
	}
	bool tag=true,f1=true,f2=true;
	for(int i=0;a[i]<3 && i<n;i++){
		if(a[i]==0) continue;
		int x=a[i],sum;
		for(int j=i+1;x && j<n;j++)
			if(a[j]==3) x--;
		if(x) f1=false;
		else{
			if(d[i]>a[i]) sum=a[i];
			else sum=d[i];
		}
		x=3-a[i];
		for(int j=i+1;x && j<n;j++)
			if(a[j]==4) x--;
		if(x) f2=false;
		if(f1 || f2){
			if(f1 && f2) ans+=min(sum,3-a[i]);
			else if(f1) ans+=sum;
			else ans+=3-a[i]; 
		}else tag=false;
		break;
	}
	if(tag) printf("%d", ans);
	else puts("-1");
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值