ICode9

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

P4145 上帝造题的七分钟2 / 花神游历各国

2020-11-26 20:35:54  阅读:238  来源: 互联网

标签:txt rr int ll long 七分钟 P4145 造题 include


P4145 上帝造题的七分钟2 / 花神游历各国

目录

题目

传送门

思路

听说直接暴力处理每一次更改+树状数组查询+小优化就能过这道题?!

emm

我是为了练分块才找到这道题的,所以自然是用分块啦

首先,要明白,1e12最多也就是进行6次开平方操作就能变成1(详见下:源自程序计算)

1000000000000
1000000
1000
31
5
2
1
1

我们设a[i][j]表示原输入数列中的第i个数进行j次开平方后得到的数,因此,当j为0时,就是原来的数列

按老规矩定义int L[max_t] , R[max_t];int pos[nn];,不会的去分块模板

另外定义int upd[i]表示第i个块整体开平方的次数

查询

对于每一次查询(不再赘述,直接看代码):

ll query(rr int l , rr int r) {
	rr int p = pos[l] , q = pos[r];
	rr ll ans = 0;
	if(p == q) {//l,r属于同一个块
		for(int i = l ; i <= r ; ++i)
			ans += a[i][upd[p]];
		return ans;
	}
	for(rr int i = l ; i <= R[p] ; ++i)//开头
		ans += a[i][upd[p]];
	
	for(rr int i = p + 1 ; i <= q - 1 ; ++i)//中间
		ans += sum[i][upd[i]];
	
	for(rr int i = L[q] ; i <= r ; ++i)//结尾
		ans += a[i][upd[q]];
	
	return ans;
}

修改

然后对于每一次修改:

void change_(int l , int r , int p) {//暴力修改第p个块暴力将[l,r]的数开平方
	if(upd[p] == 7)return;//小优化,等下讲
	for(int i = l ; i <= r ; ++i)
		for(int j = 0 ; j <= 6 ; ++j)
			a[i][j] = a[i][j + 1];
	for(int j = 0 ; j <= 7 ; ++j) {//更新sum[p]
		sum[p][j] = 0;
		for(int i = L[p] ; i <= R[p] ; ++i)
			sum[p][j] += a[i][j];
	}
}
void change(int l , int r) {
	if(cnt <= 0)return;
	int p = pos[l] , q = pos[r];
	if(p == q) {//l,r属于同一个块
		change_(l , r , p);
		return;
	}
	change_(l , R[p] , p);//开头一段
	for(int i = p + 1 ; i <= q - 1 ; ++i)//中间
		if(upd[i] < 7)++upd[i],--cnt;
	change_(L[q] , r , q);//结尾
	
}

优化

结果发现,交上去是50分(TLE)

我们的时间效率为 \(O(n\sqrt n)\) 大概在1e7~1e8左右,但是前面带一个"7"的常数,再加上一丢丢小优化理论上是可以过的

先是卡了一波常数,i++变为++i,变量尽量带上register,快速输出,然鹅也没有快多少

考虑到每个数进行6次开方后再开方就无意义了,所以就有了上面见到的优化:if(upd[p] == 7)return;(在void change_(int l , int r , int p)中),然后就AC了,学校的老人机也能在200ms的时间下通过单个测试数据(原2000ms)

代码(含对拍)

对拍的命名按照老规矩(见前2篇博客)

AC代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define ll long long
#define nn 100010
#define max_t 1010
#define rr register
//#pragma GCC optimize(3)
using namespace std;
long long read() {
	long long re = 0;
	char c = getchar();
	
	while(c < '0' || c > '9')c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0',
		c = getchar();
	return re;
}
int n , m , t;
ll a[nn][15];
ll sum[max_t][15];
int L[max_t] , R[max_t];
int upd[max_t];
int pos[nn];
int cnt;//cnt也是用于优化,但是已经有"思路"中的优化的情况下效果并不明显(O2优化下总时间快40ms(洛谷))
void Init() {
	memset(upd , 0 , sizeof(upd));
	for(int i = 1 ; i <= n ; ++i)
		for(int j = 1 ; j <= 7 ; ++j)
			a[i][j] = (int)sqrt(a[i][j - 1]);
	
	t = sqrt(n);
	int len = t;
	R[0] = 0;
	for(int i = 1 ; i <= t ; ++i)
		L[i] = R[i - 1] + 1 , R[i] = i * len;
	if(R[t] < n)
		++t , L[t] = R[t - 1] + 1 , R[t] = n;
	cnt = t * 7;
	for(int i = 1 ; i <= t ; ++i)
		for(int j = L[i] ; j <= R[i] ; ++j)
			pos[j] = i;
	
	for(int i = 1 ; i <= t ; ++i)
		for(int j = 0 ; j <= 7 ; ++j)
			for(int k = L[i] ; k <= R[i] ; ++k)
				sum[i][j] += a[k][j]; 
}
void change_(int l , int r , int p) {
	if(upd[p] == 7)return;//注意这里的优化,挺重要的,学校的台式机(lao ren ji)测极限数据可从2000ms优化到200ms
	for(int i = l ; i <= r ; ++i)
		for(int j = 0 ; j <= 6 ; ++j)
			a[i][j] = a[i][j + 1];
	for(int j = 0 ; j <= 7 ; ++j) {
		sum[p][j] = 0;
		for(int i = L[p] ; i <= R[p] ; ++i)
			sum[p][j] += a[i][j];
	}
}
void change(int l , int r) {
	if(cnt <= 0)return;
	int p = pos[l] , q = pos[r];
	if(p == q) {
		change_(l , r , p);
		return;
	}
	change_(l , R[p] , p);
	for(int i = p + 1 ; i <= q - 1 ; ++i)
		if(upd[i] < 7)++upd[i],--cnt;
	change_(L[q] , r , q);
	
}
ll query(rr int l , rr int r) {
	rr int p = pos[l] , q = pos[r];
	rr ll ans = 0;
	if(p == q) {
		for(int i = l ; i <= r ; ++i)
			ans += a[i][upd[p]];
		return ans;
	}
	for(rr int i = l ; i <= R[p] ; ++i)
		ans += a[i][upd[p]];
	
	for(rr int i = p + 1 ; i <= q - 1 ; ++i)
		ans += sum[i][upd[i]];
	
	for(rr int i = L[q] ; i <= r ; ++i)
		ans += a[i][upd[q]];
	
	return ans;
}
void output(ll x) {
	if(x >= 10)output(x / 10);
	putchar(x % 10 + '0');
}
int main() {
	n = read();
	for(rr int i = 1 ; i <= n ; i++)
		a[i][0] = read();
	Init();
	m = read();
	for(int i = 1 ; i <= m ; ++i)  {
		int op = read() , l = read() , r = read();
		if(l > r){rr int tmp = l ; l = r ; r = tmp;}
		if(op == 0)	change(l , r);
		else {
			/*
			printf("%lld\n" , query(l , r));
			/*/
			output(query(l , r));
			putchar('\n');
			//*/
		}
	}
	return 0;
}

暴力

#include <bits/stdc++.h>
#define ll long long
using namespace std;
long long read() {
	long long re = 0;
	char c = getchar();
	
	while(c < '0' || c > '9')c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0',
		c = getchar();
	return re;
}

int n , m;
ll a[100010];
int main() {
	n = read();
	for(int i = 1 ; i <= n ; i++)
		a[i] = read();
	
	m = read();
	for(int i = 1 ; i <= m ; i++) {
		int op = read() , l = read() , r = read();
		if(l > r) swap(l , r);
		if(op == 0)
			for(int j = l ; j <= r ; j++)
				a[j] = (int)sqrt(a[j]);
		else {
			ll ans = 0;
			for(int j = l ; j <= r ; j++) {
				ans += a[j];
			}
			printf("%lld\n" , ans);
		}
	}
		
	return 0;
}

数据生成

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll random(ll r , ll l = 1) {
	return l == r ? l : abs((ll)rand() * rand() % (r - l) + l);
}
int main() {
	srand((unsigned)(time(0)));
	
	int n = random(100000 , 100000);
	printf("%d\n" , n);
	for(int i = 1 ; i <= n ; i++)
		printf("%lld " , random(1000000000000ll));
	putchar('\n');
	
	int m = random(100000 , 100000);
	printf("%d\n" , m);
	for(int i = 1 ; i <= m ; i++) {
		printf("%d %d %d\n" , random(100) % 2 ^ 1 , random(n) , random(n));
	}
	return 0;
}

对拍控制

#include <bits/stdc++.h>
using namespace std;
int main() {
	int cnt = 0;
	while(true) {
		++cnt;
		printf("\n#%d\n" , cnt);
		system("random.exe > input.txt");
		puts("random");
		
		int t = clock();
		if(system("tested < input.txt > output2.txt") != 0) {
			cout << "RE";
			break;
		}
		puts("tested");
		printf(">time : %d\n" , clock() - t);
		continue;//删掉这里开启对拍,否则为单纯性能测试
		
		system("std.exe < input.txt > output1.txt");
		puts("std");
		
		if(system("fc output1.txt output2.txt")) {
			cout << "WA";
			break;
		}
	}
	system("start input.txt"); 
	return 0;
}

标签:txt,rr,int,ll,long,七分钟,P4145,造题,include
来源: https://www.cnblogs.com/dream1024/p/14044350.html

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

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

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

ICode9版权所有