【brute force/two pointers+divide and conquer/rmq】 educational codeforces round 94

10 篇文章 0 订阅

D. Zigzags

传送门

题意:在这里插入图片描述

思路:

  1. 把问题转化为map来看:找 ( a i , a j ) = ( a k , a l ) (a_i,a_j)=(a_k,a_l) (ai,aj)=(ak,al)的个数
  2. 数据小:双层循环:外层从后往前遍历 k k k,再从 k k k往前遍历 i i i
  3. 第二层循环过程中途径的都是 a j a_j aj,记录多少个 a j = a l a_j=a_l aj=al
  4. 遇到 a i = a k a_i=a_k ai=ak时,贡献为遍历途中多少个 a j = a l a_j=a_l aj=al

代码:

#include<bits/stdc++.h>
using namespace std;
#define fore(i,x,y) for(int i=x;i<=y;++i)
const int N = 3004;
typedef long long ll;
int a[N],cnt[N];
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		fore(i,1,n) scanf("%d",&a[i]);
		ll k,ans=0;
		memset(cnt,0,sizeof(cnt));
		for(int i=n;i;--i){
			k=0;
			for(int j=i-1;j;--j){
				if(a[i]==a[j]) ans+=k;
				k+=cnt[a[j]];
			}
			cnt[a[i]]++;
		}
		printf("%lld\n",ans);
	}
}

E. Clear the Multiset

传送门

题意:

一个multiset,a[i]意味着有a[i]个i数字,两种操作,(1)选一个i减少任意个(2)一个区间减少一个。用最少操作清空multiset。

思路:

  1. 顺序随意,固考虑先操作2再操作1。
  2. 分治:对每个状态,比较纯操作2优还是操作1后转移到下一个状态优
  3. 每次操作1必然是选取区间最小值,全员减这个最小值(故此处可用rmq优化为O(n))

代码:

时间复杂度:O(n^2)

#include<bits/stdc++.h>
using namespace std;
#define fore(i,x,y) for(int i=(x);i<=(y);++i)
const int N = 5003;
typedef long long ll;
ll inf = 1e10;
int a[N];
int rmq(int l,int r){
	ll m=inf;int x;
	fore(i,l,r) if(a[i]<m) m=a[i],x=i;
	return x;
}
ll solve(int l,int r,int h){
	if(l>r) return 0;
	int m=rmq(l,r);
	return min((ll)r-l+1,solve(l,m-1,a[m])+solve(m+1,r,a[m])+a[m]-h);
}
int main(){
	int n;
	scanf("%d",&n);
	fore(i,1,n) scanf("%d",&a[i]); 
	printf("%lld\n",solve(1,n,0));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值