Codeforces Round #433(Div. 1,based on Olympiad of Metropolises)A Planning B Jury Meeting C Boredom

人生的第一次div.1 掉分 QAQ

A - Planning

http://codeforces.com/contest/853/problem/A

贪心,排个序,优先安排花费大的,用模拟链表实现的

#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
struct node
{
	int t,index;
}a[1000005];
int cmp(node u,node v)
{
	return u.t>v.t;
}
int pre[1000005],ne[1000005];
int ans[1000000];
int book[1000000];
int main()
{
	int n,k,i;
	cin>>n>>k;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i].t);
		a[i].index=i;
	}
	for(i=0;i<=1000000;i++)
	{
		if(i!=0)
		pre[i]=i-1;
		ne[i]=i+1;
	}
	sort(a+1,a+1+n,cmp);
	long long sum=0;
	int now=k+1;
	for(i=1;i<=n;i++)
	{
		if(a[i].index<=now)
		{
			sum+=1ll*(now-a[i].index)*a[i].t;
			ans[a[i].index]=now;
			ne[pre[now]]=ne[now];
			pre[ne[now]]=pre[now];
			now=ne[now];	
		}
		else
		{
			ans[a[i].index]=a[i].index;
			ne[pre[a[i].index]]=ne[a[i].index];
			pre[ne[a[i].index]]=pre[a[i].index];	
		}
	}
	cout<<sum<<endl;
	for(i=1;i<=n;i++)
	printf("%d ",ans[i]);
	cout<<endl;
 }


B - Jury Meeting

http://codeforces.com/contest/853/problem/B

题意看了半天,看懂题意,其实就很水了。。

也是排个序,记录一下前缀最小花费,后缀最小花费,最后扫一遍就可以了

#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
int n,m,k;
long long dp[2][1000005];
long long need[2][1000005];
struct node
{
	int d,f,t,c;
}a[100005];
int cmp(node u,node v)
{
	return u.d<v.d;
}
const ll inf=0x3f3f3f3f3f3f3f3f;
int main()
{
	int i;
	cin>>n>>m>>k;
	for(i=0;i<m;i++)
	{
		scanf("%d %d %d %d",&a[i].d,&a[i].f,&a[i].t,&a[i].c);	
	}
	sort(a,a+m,cmp);
	memset(need,-1,sizeof(need));
	memset(dp,inf,sizeof(dp));
	ll sum=0,now=0;
	for(i=0;i<m;i++)
	{
		if(a[i].f)
		{
			if(need[0][a[i].f]==-1)
			{
				now++;
				sum+=a[i].c;
				need[0][a[i].f]=a[i].c;
			}
			else if(a[i].c<need[0][a[i].f])
			{
				sum+=a[i].c-need[0][a[i].f];
				need[0][a[i].f]=a[i].c;
			}
			if(now==n)
			{
				dp[0][a[i].d]=min(dp[0][a[i].d],sum);
			}
		}
	}
	now=0,sum=0;
	for(i=m-1;i>=0;i--)
	{
		if(a[i].t)
		{
			if(need[1][a[i].t]==-1)
			{
				now++;
				sum+=a[i].c;
				need[1][a[i].t]=a[i].c;
			}
			else if(a[i].c<need[1][a[i].t])
			{
				sum+=a[i].c-need[1][a[i].t];
				need[1][a[i].t]=a[i].c;
			}
			if(now==n)
			{
				dp[1][a[i].d]=min(dp[1][a[i].d],sum);
			}
		}
	}
	for(i=1;i<=1000000;i++)
	{
		dp[0][i]=min(dp[0][i],dp[0][i-1]);
	}
	for(i=1000000;i>=0;i--)
	{
		dp[1][i]=min(dp[1][i],dp[1][i+1]);
	}
	long long ans=inf;
	for(i=0;i+k<=1000000;i++)
	{
		ans=min(ans,dp[0][i]+dp[1][i+k+1]);
	}
	if(ans==inf)
	cout<<-1<<endl;
	else
	cout<<ans<<endl;
	return 0;
 }
C - Boredom
http://codeforces.com/contest/853/problem/C

主席树,主席树主要是用来快速统计某个子矩阵里标记点的个数,因为每列只被标记一个,所以主席树可以搞,但当时思路并不是很清晰,手速也太慢,后来想通了其实也还好

这样就可以快速的查询某个子矩阵里标记点的个数,对于每个查询的矩阵,我们只需要求不在这个矩阵里的所有 beautiful rectangles个数即可,也就是两个被标记的点都在查询矩阵的上方,下方,左方,右方,最后在去一下重。


#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int l[30*maxn],r[30*maxn],sz[30*maxn];
int tot=0,t[maxn],p[maxn];
int build(int le,int ri)
{
    int root=tot++;
    sz[root]=0;
    int m=(le+ri)>>1;
    if(le!=ri)
    {
        l[root]=build(le,m);
        r[root]-build(m+1,ri);
    }
    return root;
}
int update(int root,int le,int ri,int x,int k)
{
    int now=tot++;
    sz[now]=sz[root]+k;
    if(le==ri)
        return now;
    int m=(le+ri)>>1;
    if(x<=m)
    {
        l[now]=update(l[root],le,m,x,k);
        r[now]=r[root];
    }
    else
    {
        r[now]=update(r[root],m+1,ri,x,k);
        l[now]=l[root];
    }
    return now;
}
int query(int root,int le,int ri,int L,int R)
{
    if(L>R)
        return 0;
    if(L<=le&&R>=ri)
    {
        return sz[root];
    }
    if(le==ri)
    {
        return sz[root];
    }
    int sum=0;
    int m=(le+ri)>>1;
    if(m>=L)
    {
        sum+=query(l[root],le,m,L,R);
    }
    if(m<R)
    {
        sum+=query(r[root],m+1,ri,L,R);
    }
    return sum;
}
inline long long f(int x)
{
    return 1ll*x*(x-1)/2;
}
int main()
{
	int i,n,q,l,r,u,d;
	cin>>n>>q;

	t[0]=build(1,n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&p[i]);
		t[i]=update(t[i-1],1,n,p[i],1);
	}
	long long ans=0;
//	cout<<query(t[0],1,n,1,n)<<endl;
	while(q--)
	{
	    ans=f(n);
		scanf("%d %d %d %d",&l,&d,&r,&u);
		int temp1=query(t[n],1,n,1,n)-query(t[r],1,n,1,n);
		int temp2=query(t[n],1,n,u+1,n);
		int temp3=temp2-query(t[r],1,n,u+1,n);
		int temp4=query(t[l-1],1,n,1,n);
		int temp5=query(t[n],1,n,1,d-1);
		int temp6=temp5-query(t[r],1,n,1,d-1);
		int temp7=temp4-query(t[l-1],1,n,1,u);
		int temp8=query(t[l-1],1,n,1,d-1);
	//	cout<<temp1<<" "<<temp2<<" "<<temp3<<" "<<temp4<<" "<<temp5<<" "<<temp6<<" "<<temp7<<" "<<temp8<<endl;
		ans-=f(temp1)+f(temp2)+f(temp4)+f(temp5)-f(temp3)-f(temp7)-f(temp8)-f(temp6);
		printf("%lld\n",ans);
	}
	return 0;
 }




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值