• BZOJ2093: [Poi2010]Frog


    此题倍增比较好想

    找第 k 近的点感觉不是很好想

    没有想到啊——

    两个指针扫维护里当前点最近的 k + 1 个点, +1 是因为还要算上当前点
    考虑当 i + 1 时 l,r 的移动,为了保证最小,要把右端点+1的点和左端点进行比较,
    若 pos[r + 1] - pos[i] < pos[i] - pos[l],就平移整个区间

    此时可以选择倍增,需要滚动数组,就每次倍增的时候不断更新
    ans[i] 表示从第 i 个点出发,当前跳到了 ans[i], 每次更新跳了 2^i 跳到哪
    总共更新 log(m) 次就好了

    或者跑个置换(?)快速幂就好了

    听说以后polya要用就当板子写的

    感觉思想和倍增差不多?

    在 BZOJ 上加了输优才过。。。

    比倍增还慢。。


    代码:

    快速幂:

    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cstdio>
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 1000005;
    
    int n, k;
    ll m, pos[MAXN];
    struct TRN{
    	int arr[MAXN];
    	int& operator [] (int x) {
    		return arr[x];
    	}
    	void operator *= (TRN &b) {
    		static TRN tmp;
    		for(int i = 1; i <= n; ++i) 
    			tmp[i] = b[arr[i]];
    		memcpy(this, &tmp, sizeof(TRN));
    		return;
    	}
    }to, ans;
    
    inline int rd() {
    	register int x = 0;
    	register char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)) {
    		x = x * 10 + (c ^ 48);
    		c = getchar();
    	}
    	return x;
    }
    inline ll rdll() {
    	register ll x = 0ll;
    	register char c = getchar();
    	register bool f = false;
    	while(!isdigit(c)) {
    		f = (c == '-');
    		c = getchar();
    	}
    	while(isdigit(c)) {
    		x = x * 10ll + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    inline void write(int x) {
    	register int y = 10, len = 1;
    	while(y <= x) {y *= 10; ++len;}
    	while(len--) {y /= 10; putchar(x / y + 48); x %= y;}
    	return;
    }
    inline void fastpow(TRN &t, ll top) {
    	while(top) {
    		if(top & 1ll) ans *= t;
    		t *= t;
    		top >>= 1;
    	}
    	return;
    }
    
    int main() {
    	n = rd(); k = rd(); m = rdll();
    	for(int i = 1; i <= n; ++i) 
    		pos[i] = rdll();
    	int l = 1, r = k + 1;
    	for(int i = 1; i <= n; ++i) {
    		while((r < n) && (pos[r + 1] - pos[i] < pos[i] - pos[l])) {++l; ++r;}
    		to[i] = ((pos[i] - pos[l] >= pos[r] - pos[i]) ? (l) : (r));
    		ans[i] = i;
    	}
    	fastpow(to, m);
    	for(int i = 1; i < n; ++i) {
    		write(ans[i]);
    		putchar(' ');
    	}
    	write(ans[n]);
    	putchar('
    ');
    	return 0;
    }

    倍增:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 1000005;
    
    int n, k, lg;
    int to[2][MAXN], ans[MAXN];
    ll m, pos[MAXN], pwr[70];
    
    inline int rd() {
    	register int x = 0;
    	register char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)) {
    		x = x * 10 + (c ^ 48);
    		c = getchar();
    	}
    	return x;
    }
    inline ll rdll() {
    	register ll x = 0ll;
    	register char c = getchar();
    	register bool f = false;
    	while(!isdigit(c)) {
    		f = (c == '-');
    		c = getchar();
    	}
    	while(isdigit(c)) {
    		x = x * 10ll + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    
    int main() {
    	n = rd(); k = rd(); m = rdll();
    	lg = log2(m) + 1;
    	pwr[0] = 1ll;
    	for(int i = 1; i <= lg; ++i) pwr[i] = (pwr[i - 1] << 1);
    	for(int i = 1; i <= n; ++i) pos[i] = rdll();
    	int l = 1, r = k + 1;
    	for(int i = 1; i <= n; ++i) {
    		while(r < n && pos[r + 1] - pos[i] < pos[i] - pos[l]) {++l; ++r;}
    		to[0][i] = ((pos[i] - pos[l] >= pos[r] - pos[i]) ? (l) : (r));
    	}
    	if(m & 1) for(int i = 1; i <= n; ++i) ans[i] = to[0][i];
    	else for(int i = 1; i <= n; ++i) ans[i] = i;
    	int cur = 1;
    	for(int i = 1; i <= lg; ++i) {
    		for(int j = 1; j <= n; ++j) to[cur][j] = to[cur ^ 1][to[cur ^ 1][j]];
    		if((m & pwr[i])) for(int j = 1; j <= n; ++j) ans[j] = to[cur][ans[j]];
    		cur ^= 1;
    	}
    	for(int i = 1; i < n; ++i) printf("%d ", ans[i]);
    	printf("%d
    ", ans[n]);
    	return 0;
    }
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    让owncloud成为微博式记事本
    软件即抽象
    十年,最后一个alpha,0.4.1版的reactos终于变得可赏可玩了
    使用群晖作mineportalbox(1):合理且不折腾地使用群晖硬件和套件
    使用群晖作mineportalbox(2):把webstation打造成snippter空间
    使用群晖作mineportalbox(3):在阿里云上单盘安装群晖skynas
    统一的分布式数据库和文件系统mongodb,及其用于解决aliyun上做站的存储成本方案
    吃桃
    1020: C语言程序设计教程(第三版)课后习题6.9
    分数序列
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9752463.html
Copyright © 2020-2023  润新知