ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

220529 总结

2022-05-29 14:31:08  阅读:121  来源: 互联网

标签:总结 int 220529 dfs leq long sumqb 翻转


220529 总结

预计:\(100+100+40\)

自测:\(50+40+30\)

一个小时写完了前两题,剩的两小时里面用半小时写了个深搜,剩下的时间一直在调T3(

怎么全是极端数据

挂大分

T1 小麦亩产一千八

斐波那契数列题

每个格子的小麦数序列为 \(\{1,x,x+1,2x+1,3x+2,\dots\}\)

预处理出斐波那契数列前 \(30\) 项,计算出 \(x\) 的值后计算结果即可

注意到 \(1\leq p \leq 10^6\) ,要开 \(\text{long long}\)

嗯然后我读入 \(x\) 的时候没开 \(\text{long long}\) 白挂 \(50\) 分

T2 休息

考的时候直接上的模拟

因为我写的是扫一遍能把所有的区间都翻转一遍觉得足够了就没去写优化

又因为后六个点全是极端数据所以后六个点一个没过

但显然还是不够

第一次翻转之后,由于翻转后是若干段断开的单调区间,所以再翻转仅能在两个区间的交界处发生

我虽然发现了这一性质,但是我不知道该怎么用(

看了学姐博客,发现可以利用这一性质通过求逆序对来快速求解(毕竟每次翻转只会翻转若干个长度为2的区间,就相当于是交换相邻的逆序对了)

#include<bits/stdc++.h>
using namespace std;

#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)

const int maxN = 4e5;

int N;
int books[maxN];

int T[maxN];
long long cnt;

void merge(int l,int r){
	int mid = (l + r) >> 1;
	int p1 = l;
	int p2 = mid+1;
	int p = l;
	while(p1 <= mid && p2 <= r){
		if(books[p1] < books[p2]){
			T[p++] = books[p1++];
		}else{
			T[p++] = books[p2++];
			cnt += mid - p1 + 1;
		}
	}
	while(p1 <= mid) T[p++] = books[p1++];
	while(p2 <= r) T[p++] = books[p2++];
	for(int i = l;i<=r;i++) books[i] = T[i];
}

void mergeSort(int l,int r){
	if(l == r) return;
	int mid = (l + r) >> 1;
	mergeSort(l,mid);
	mergeSort(mid+1,r);
	merge(l,r);
}

int main() {
	FO("rest");
	scanf("%d",&N);
	for(int i = 1; i<=N; i++) {
		scanf("%d",&books[i]);
	}
	books[N+1] = 1e9;

	int st = 1;
	int ed = 1;
	for(int i = 2; i<=N+1; i++) {
		if(books[i] < books[ed]){
			ed = i;
		}else{
			if(st != ed) cnt++;
			int len = (ed - st + 1) >> 1;
			for(int j = 1;j<=len;j++){
				swap(books[st+j-1],books[ed-j+1]);
			}
			ed = st = i;
		}
	}
	mergeSort(1,N);
	printf("%lld\n",cnt);
	return 0;
}

T3 军训

考场上用的 DFS ,但由于 $1 \leq N \leq 20000 $ ,在 \(n \gt 10000\) 会由于递归层数太多而爆栈

(不过在 \(1 \leq N \leq 10000\) 算法的确是正确的)

//非常朴素的dfs写法,仅能过 40% 的数据
//dfs(学号,女友指数最高的班级的女友指数,这个班级女友值,这个班级欠扁值,所有班级欠扁值总和)
void dfs(int k,int maxny,int sumny,int qbz,int sumqb){
	if(k > N){
		if(sumqb > LIMIT) return;
		ans = min(ans,maxny);
		return;
	}
	if(sumny >= ans) return;
	if(sumqb > LIMIT) return;

	//新开班,第k个学生在新班 
	dfs(k+1,max(maxny,gf[k]),gf[k],qb[k],sumqb+qb[k]);
	
	//插入旧班,第k个学生在旧班
	dfs(k+1,max(maxny,sumny+gf[k]),sumny+gf[k],max(qbz,qb[k]),sumqb-qbz+max(qbz,qb[k])); 
}

后来想把 \(20000\) 拆成两半分别递归后再合并结果但是没写明白(

标签:总结,int,220529,dfs,leq,long,sumqb,翻转
来源: https://www.cnblogs.com/burnling/p/16323798.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有