ICode9

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

高考集训3

2022-06-07 16:04:12  阅读:123  来源: 互联网

标签:int 高考 void maxn inline LL 集训 define


e.....又是一场水过的考试,话说今天除了T3多少都跟dp有亲戚关系,真tm是个大家族啊

至于代码下边的歌词....别问,问就是因为做完唯一一道熟悉的T4之后啥也不会只能背歌词...背着背着就会了。。。(小妙招+1)

鉴于学长的建议(倡议),以后就不粘题面了
image

T1 Watching Fireworks is Fun

这个题确实是个很裸的dp,但是考试的时候没优化...O(m * n ^ 2)的复杂度确实是炸
具体的看代码,就写下优化
所以就拿单调队列维护一下位置
每一个时间只和上一个时间有关系,可以用滚动数组了,所以最后就是dp[2][2e5]
如果不是同一时刻绽放的烟花,是有移动距离的,这一段距离的最大幸福度用单调队列来找到。
这个就是我们枚举每一个 j 的位置,上一个烟花在 j 两边左右为 d*t 的距离绽放都是可以让这一个烟花在 j 位置绽放
image
对每一次 烟花 的每一个位置 j 我们都要求 长度为 2 * d * t[i] 区间内的最大值,那么问题又变成 求 滑动窗口内的 最大值。注意这里的窗口长度有左右两部分 。

点击查看代码
#define WMX aiaiaiai~~~
#include <bits/stdc++.h>
#define LL long long 
#define Re register int
#define ki cout << endl 
#define LD double
#define frein(x) freopen(#x ".txt", "r", stdin);
#define freout(x) freopen(#x ".txt", "w", stdout);
using namespace std;
//唉,虽然今天是败犬,但是也得继续啊
//《tian gou de ri chang》
namespace kiritokazuto {
	template <typename T> inline void in(T &x) {
		int f = 0; x = 0; char c = getchar();
		while(c < '0' || c > '9')f |= c == '-', c = getchar();
		while(c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
		x = f ? -x : x;
	}
	template <typename T> inline void ot(T x) {
		if(x < 0)putchar('-'), x = - x;
		if(x > 9)ot(x / 10);putchar(x % 10 | '0');
	}
}
using namespace kiritokazuto;
//为啥T1就像不可做的玩意

//看着就像是一道ex的dp,话说t1,t2都是dp真的ex

const int maxn = 2e5 + 10; 
const LL Inf = 0x7fffffffffff;
LL dp[2][maxn];//开是开不下的,先部分分吧
//dp[i][j]放第 i 个烟花时,位置 j 最大快乐值。

//样例两个过一个...随缘
//这个距离怎么考虑????

inline LL maxx(LL a, LL b) {return a > b ? a : b;}
LL n, m, d;
LL a[maxn], b[maxn], t[maxn];
LL q[maxn];
signed main () {
    //frein(in);
   // freout(out);
     freopen("fire.in", "r", stdin);
     freopen("fire.out", "w", stdout);
    in(n);
    in(m);
    in(d);
    for(Re i = 1; i <= m; i ++) {
        in(a[i]);
        in(b[i]);
        in(t[i]);
    }
//cout << "KKKK" << endl;
    memset(dp, 0x7f, sizeof(dp));
    memset(q, 0, sizeof(q));
    for(Re i = 1; i <= n; i ++)dp[0][i] = 0;
    int op = 1;
    
    for(Re i = 1; i <= m; i ++) {
        int hd = 1, tl = 0;
        int tmp = 1;
        for(Re j = 1; j <= n; j ++) {
            for(;tmp <= min(n, j + d * (t[i] - t[i - 1]));tmp++){
                while(hd <= tl && dp[op ^ 1][q[tl]] <= dp[op ^ 1][tmp]) tl--;
                q[++tl] = tmp;
            }
            while(hd <= tl && q[hd] < min(n, j - d * (t[i] - t[i - 1]))) hd++;
            dp[op][j] = dp[op ^ 1][q[hd]] + b[i] - abs(a[i] - j);
        }
        op = op ^ 1;
    }
    LL ans = -Inf;
    for(Re i = 1; i <= n; i ++) {
        ans = maxx(ans, dp[op ^ 1][i]);
    }
    cout << ans;
    return 0;
}

 

/*
时光洪流中这份爱多渺小,一放手就消散掉
你的心飘向远方,我留不住也好
酸与苦比恨要好,所有的滋味都在夜里品尝
天亮就继续微笑,我知道我可以做到
*/

T2Perform巡回演出

就是用题解的方法硬dp就行,就是记得把初值设好。。。因为初始化白丢70pts
记得把第一天初始化好,如果初始化0的话可能会爆

点击查看代码
#define WMX aiaiaiai~~~
#include <bits/stdc++.h>
#define LL long long 
#define Re register int
#define ki cout << endl 
#define LD double
#define frein(x) freopen(#x ".txt", "r", stdin);
#define freout(x) freopen(#x ".txt", "w", stdout);
using namespace std;
//唉,虽然今天是败犬,但是也得继续啊
//《tian gou de ri chang》
namespace kiritokazuto {
	template <typename T> inline void in(T &x) {
		int f = 0; x = 0; char c = getchar();
		while(c < '0' || c > '9')f |= c == '-', c = getchar();
		while(c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
		x = f ? -x : x;
	}
	template <typename T> inline void ot(T x) {
		if(x < 0)putchar('-'), x = - x;
		if(x > 9)ot(x / 10);putchar(x % 10 | '0');
	}
}
using namespace kiritokazuto;
//这个题干排版啊...
//话说2000年我还妹出生啊
//这题读入是个啥呀????

const int maxn = 1 + 10;
int dp[maxn * 100][maxn];//标准定义为,第i天到达第j个城市的ans
struct Node {
	int cir;//周期
	int w[31];//每天的价钱
}wmx[maxn][maxn];//还好城市少....
int n, k;

signed main () {
  //  frein(in);
  //  freout(out);
     freopen("perform.in", "r", stdin);
     freopen("perform.out", "w", stdout);
	///啊啊啊啊我透,烦死了,,,,这玩意他是多组....
	//不不不,这玩意样例不是3组吗???
	//..................读题!!! 0 0 结束....
	while(scanf("%d %d", &n, &k) != EOF) {
	//	cout << "sss" << endl;
		memset(wmx, 0, sizeof(wmx));
		memset(dp, 0x7f, sizeof(dp));
		if(n == 0 && k == 0) break;//结束.....	
		for(Re i = 1; i <= n; i ++) {
			for(Re j = 1; j <= n; j ++) {
				if(i != j) {
					in(wmx[i][j].cir);
					for(Re kk = 1; kk <= wmx[i][j].cir; kk ++) {
						in(wmx[i][j].w[kk]);
					}
					// for(Re kk = 1; kk <= wmx[i][j].cir; kk ++) {
					// 	cout << wmx[i][j].w[kk] << endl;
					// }
				}
			}
		}
		
	//	cout << "kkk" << endl;
		for(Re i = 1; i <= n; i ++) if(wmx[1][i].w[1] != 0)dp[1][i] = wmx[1][i].w[1];
		// for(Re i = 1; i <= n; i ++) {
		// 	cout << dp[1][i] << endl;
		// }
		//论初始化的重要性....昨天T4就炸了
	//	cout << "mmmm" << endl;
		for(Re i = 2; i <= k; i ++) {
			for(Re j = 1; j <= n; j ++) {
				for(Re kk = 1; kk <= n; kk ++) {
					//。。。因为我从一存,所以一个特别尴尬的事就发生了....
					//我他喵直接膜会爆掉,所以i % cir就变成了(i - 1) % cir + 1
					 if((j != kk) && (wmx[kk][j].w[(i - 1) % wmx[kk][j] . cir + 1] != 0)){
               		   if(!dp[i][j]) dp[i][j] = dp[i-1][kk] + wmx[kk][j].w[(i - 1) % wmx[kk][j].cir + 1];//直接赋值,别取min或者初始化成max。。。。要不然这数太奇怪..
					   else dp[i][j] = min(dp[i][j], dp[i-1][kk] + wmx[kk][j].w[(i - 1) % wmx[kk][j].cir + 1]);
					}
				}
			}
		}

	//	cout << "LLl" << endl;
	if(dp[k][n] > 100000)cout << 0 << endl;
    else cout << dp[k][n] << endl;
	}

    return 0;
}
/*
我预演过千次百次的重逢,你却始终站在梦里难触碰
太难回头只能一直走不停,曾经两个人流失人海之中
*/

贺俊鹏(whp)有个记搜的

点击查看代码
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
inline int in(){
    int x = 0;
    bool f = 1;
    char c = getchar();
    while(c > '9' || c < '0'){
        if(c == '-') f ^= 1;
        c = getchar();
    }
    while(c <= '9' && c >= '0'){
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    if(f) return x;
    else return -x;
}
//dfs?
//好像会炸
//再加个记忆化呢
//emmm...大的数据太慢
int n,m;
int a[15][15][35];
ll ans = 0;
bool bj = 0;
int jl[15][1010];//jl[i][k]第k天到达i的最小费用,记忆化搜索
inline void dfs(int x,int t,ll val){
    if(t == m+1){
        if(x == n){
            bj = 1;
            ans = min(ans,val);
        }
        return;
    }
    // printf("return?\n");
    if(jl[x][t] && val >= jl[x][t]) return;
    jl[x][t] = val;
    // printf("No!\n");
    // printf("x:%d t:%d val:%lld\n",x,t,val);
    int tm = t;
    for(int i = 1;i <= n;++i){
        if(i == x) continue;
        tm = t%a[x][i][0];
        if(!tm) tm = a[x][i][0];
        // printf("-> to:%d time:%d\n",i,tm);
        // printf("have huiji?\n");
        if(!a[x][i][tm]) continue;
        // printf("Yes!\n");
        dfs(i,t+1,val+a[x][i][tm]);
    }
}
int main(){
    freopen("perform.in","r",stdin);
    freopen("perform.out","w",stdout);
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    n = in();
    while(n != 0){
        m = in();
        int t;
        ans = 1e18;
        bj = 0;
        memset(jl,0,sizeof(jl));
        for(int i = 1;i <= n;++i){
            for(int j = 1;j <= n;++j){
                if(i == j) continue;
                t = a[i][j][0] = in();
                for(int k = 1;k <= t;++k) a[i][j][k] = in();
            }
        }
        dfs(1,1,0);
        if(bj) printf("%lld\n",ans);
        else printf("0\n");
        n =in();
    }
    return 0;
}

T3 枪战Maf

具体写代码里了,挺巧的一道

点击查看代码
#define WMX aiaiaiai~~~
#include <bits/stdc++.h>
#define LL long long 
#define Re register int
#define ki cout << endl 
#define LD double
#define frein(x) freopen(#x ".txt", "r", stdin);
#define freout(x) freopen(#x ".txt", "w", stdout);
using namespace std;
//唉,虽然今天是败犬,但是也得继续啊
//《tian gou de ri chang》
namespace kiritokazuto {
	template <typename T> inline void in(T &x) {
		int f = 0; x = 0; char c = getchar();
		while(c < '0' || c > '9')f |= c == '-', c = getchar();
		while(c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
		x = f ? -x : x;
	}
	template <typename T> inline void ot(T x) {
		if(x < 0)putchar('-'), x = - x;
		if(x > 9)ot(x / 10);putchar(x % 10 | '0');
	}
}
using namespace kiritokazuto;
const int maxn = 1e6 + 10;
//我咋感觉这个题就是个求...强连通...个屁啊??
//tarjian之魂刚燃起来就灭了, 但是好像确实可以缩点。。。。。太麻烦了,还是瞎搞吧
//这个题人死了可能会影响他的目标啊

//不是,这个题吧,怎么都像dp呢,柿子捏软的,先搞T3!!!!!

//《顺序是相对的》!!!!!!!!! --陈之策

//这个题,我觉的应该逆着想,去求存活数,感觉求死亡数不好求,毕竟活着是正向
//建图去跑吧
//入度为0必定活着

/*
  1 -> 2 <- 4
	   ^
	   \ \
	      ^
		  3
3的死活取决于2的开枪顺序,标记!
样例就很灵性
*/
/*
对于一个环,要不只剩一个人,要不剩下一半(隔着打)奇环向下取整
*/
int n;
int maxx, minn;//存活人数
int aim[maxn];
bool del[maxn], live[maxn];//判断半死不活的人;
int ind[maxn];//入度
int q[maxn];//不用stl了,上次wy就被卡2000ms
int hd = 1;
///tmd忘了自环这东西了
signed main () {
    //frein(in);
    //freout(out);
     freopen("maf.in", "r", stdin);
    freopen("maf.out", "w", stdout);
	in(n);
	for(Re i = 1; i <= n; i ++) {
		in(aim[i]);
		ind[aim[i]]++;
	}
	for(Re i = 1; i <= n; i ++) {
		if(ind[i] == 0) {
			minn++;//必定活着,对于最小的而言
            q[++maxx] = i;//对于最大的维护
		}
	}
	// int tl = maxx;
	//不能这样写...maxx在更新
	while(hd <= maxx) {
		int tp = q[hd];
		hd++;
		if(del[aim[tp]])continue;//队首指向已死(一坨入度为0的点指向一个可怜
		del[aim[tp]] = 1;//否则一定是,我无敌,你必死
		int rnd = aim[aim[tp]];//随机死不死 就是3
		ind[rnd] --;//队首的目标GG了
		live[rnd] = 1;//假设活着,但随时死,若在环上可以看情况
		if(ind[rnd] == 0) q[++maxx] = rnd;//最大可加,但最小不一定
		
	}
	//因为这个题每个人都有目标,所以直接找就可以找到环
	for(Re i = 1; i <= n; i ++) {
		if(!del[i] && ind[i]) {
			int tot = 0;//环上的人
			bool fg = 0;//半死不活的人最终可以为了大业去死
			for(Re j = i; del[j] != 1; j = aim[j]) {
				tot++;
				fg |= live[j];//有一个也得记
				del[j] = 1;
			}
			// if(tot == 1) {
			// 	cout << "KKKK" << endl;
			// }
			if(!fg && tot > 1) {//不能挂等号tot = 1自环一定死
				minn++;//如果有半死不活不可以,因为剩下的可能是他
			}
			maxx += tot / 2;//半死不活直接在这考虑

		}
	}
	cout << n - maxx << " " << n - minn;
    return 0;
}
/*
时光洪流中这份爱多渺小,一放手就消散掉
我也想洒脱一笑,说一生那么长
爱与你都不重要,也许还会遇到另一个人
许下相似的诺言,我知道我难以做到
*/

T4翻转游戏

又是一道初中时候的题。。。大力枚举

点击查看代码
#define WMX aiaiaiai~~~
#include <bits/stdc++.h>
#define LL long long 
#define Re register int
#define ki cout << endl 
#define LD double
#define frein(x) freopen(#x ".txt", "r", stdin);
#define freout(x) freopen(#x ".txt", "w", stdout);
using namespace std;
//唉,虽然今天是败犬,但是也得继续啊
//《tian gou de ri chang》
namespace kiritokazuto {
	template <typename T> inline void in(T &x) {
		int f = 0; x = 0; char c = getchar();
		while(c < '0' || c > '9')f |= c == '-', c = getchar();
		while(c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
		x = f ? -x : x;
	}
	template <typename T> inline void ot(T x) {
		if(x < 0)putchar('-'), x = - x;
		if(x > 9)ot(x / 10);putchar(x % 10 | '0');
	}
}
using namespace kiritokazuto;
char s[6][6];
char wmx[6][6];
int ans = 2147483647;
int cntw;
int cntb;
int cnt;
//这个题做过
//又是初中时候的题

//ri 模了半天,结果膜错样例了。。。。模成题面上的了
//妈的,好像想起来当时的思路来着
//一行一行暴力枚举!
//4 * 4数据水到爆


// 1 -> black
// 0 -> white  

inline void did(char &x) {
    x = (x == 'w') ? 'b' : 'w';
    //这样写好像可以?
}
inline void fip(int x, int y) {
    cnt++;
    int k = x - 1;
    int kk = y - 1;
    int kkk = x + 1;
    int kkkk = y + 1;
    did(wmx[x][y]);
    did(wmx[k][y]);
    did(wmx[kkk][y]);
    did(wmx[x][kk]);
    did(wmx[x][kkkk]);
}
inline void work(int x, char c) {//c是目标
    memcpy(wmx, s, sizeof(s));
    cnt = 0;//记得归零!!!!!
    for(Re i = 1; i <= 4; i ++) {//枚举第一行所有列
        if(x & (1 << (i - 1)))fip(1, i);//不符合的反转
    }
    for(Re i = 2; i <= 4; i ++) {
        for(Re j = 1; j <= 4; j ++) {
            if(wmx[i - 1][j] != c) {//如果上一行不是目标,反,用下一行的翻上一行
                    fip(i, j);
            }
        }
    }//前三行现在完全合法,就像我对jiejie
    for(Re i = 1; i <= 4; i ++) {
        if(wmx[4][i] != c)return;
    }//最后不合法,拉跨
    ans = min(ans , cnt);

}

signed main () {
   // frein(in);
  //  freout(out);
     freopen("flip.in", "r", stdin);
     freopen("flip.out", "w", stdout);
    // for(Re i = 1; i <= 4; i ++) {
    //         // cin >> s[i][j];
    //         //  if(s[i][j] == 'b')wmx[i][j] = 1;
    //         //  else wmx[i][j] = 0;
    //         //这样转好像更慢,直接用吧
    //     scanf("%s ", s[i] + 1);
    // }
    //日,还有个0的条件
     for(Re i = 1; i <= 4; i ++) {
        for(Re j = 1; j <= 4; j ++) {
            cin >> s[i][j];
            if(s[i][j] == 'w')cntw++;
            if(s[i][j] == 'b')cntb++;
        }
     }
     if(cntw == 16 || cntb == 16) {
         cout << 0;
         return 0;
     }
    for(Re i = 0; i <= 15; i ++) {//枚举第一行的所有状态 1111是1,反转第二行的时候会影响到第一行,所以都有可能
        work(i, 'w');
        work(i, 'b');
    }
    if(ans == 2147483647) {
        cout << "Impossible";
    }else {
        cout << ans;
    }
    return 0;
}

/*
明明不甘心,明明还在等
却偏要假装,早就不痛
明明奢望着,你也再次心动
越美好期待,越容易落空
承认我不配,反倒更轻松
有些爱与妒,只有自己才懂
*/

佑的暴搜

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <ctime>
#define ll long long
#define re register int
#define char_phi signed
#define MARK "###"
#define SLEEP "

标签:int,高考,void,maxn,inline,LL,集训,define
来源: https://www.cnblogs.com/kiritokazuto/p/16352136.html

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

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

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

ICode9版权所有