计划

如果出现模考,优先模考

然后周末补掉没做的(

9.29

  • [CSP-S2019] Emiya 家今天的饭(done)
    由于直接计算可行方案数难度不亚于切黑,所以直接通过正难则反,将这道题变成求所有不合法的方案数,然后求助对于全部方案数减去这些方案即可

考虑不合法的状态,发现只需要枚举是哪种食材出现次数超过 \(\frac{k}{2}\) 即可,然后就是简单的枚举+dp

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[114][5141],dp[114][5145];
int cnt[1145];
signed main(){
    int ans=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            cnt[i]=(cnt[i]+a[i][j])%998244353;
        }
        ans*=(cnt[i]+1)%998244353;
        ans%=998244353;
    }
    ans+=998244352;
    ans%=998244353;
	for(int i=1;i<=m;i++){
		memset(dp,0,sizeof(dp));
		dp[0][0]=1;
		for(int j=1;j<=n;j++)
			for(int k=0;k<=2*(j-1);k++){
				dp[j][k]=(dp[j][k]+dp[j-1][k]*(cnt[j]-a[j][i]))%998244353;
				dp[j][k+1]=(dp[j][k+1]+dp[j-1][k])%998244353;
				dp[j][k+2]=(dp[j][k+2]+dp[j-1][k]*a[j][i])%998244353;
			}
		for(int j=n+1;j<=2*n;j++){
            ans=(ans+998244353-dp[n][j])%998244353;
        }
	}
    cout<<ans<<endl;
}
  • [SHOI2009] 会场预约(done)
    这不是优先队列板子题吗
    你可以考虑线段树维护,但是又臭又长没必要
    考虑使用我们伟大的stl库针对set同志给出的upperbound然后就可以轻松愉快的解决了!
  • [BJWC2010] 严格次小生成树(done)
    考虑对于环上的点,直接倍增找到一个环上最小的边然后替换,有一个性质是最小生成树上的边换成环上次小的边能变成非严格次小生成树,所以就有了次小生成树最小为严格次小生成树
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
	int u,v,w,pre;
	bool fg;
};
node eg[1145141],b[1145141];
int n,m,m1=0,k,head[1145141],f[1145141][22],h[1145141],zd[1145141][22],cd[1145141][22],r[1145141];
int ns1,ns2;
bool cmp(node x,node y){
	return x.w<y.w;
}
int getf(int x){
	if(x!=r[x])
		r[x]=getf(r[x]);
	return r[x];
}
void adg(int x,int y,int z){
	k++;
	b[k].v=y;
	b[k].w=z;
	b[k].pre=head[x];
	head[x]=k;
}
void dfs(int x){
	for(int i=head[x];i;i=b[i].pre){
		int y=b[i].v;
		if(h[y]){
			continue;
		}h[y]=h[x]+1;
		f[y][0]=x;
		zd[y][0]=b[i].w;
		cd[y][0]=-1;
		dfs(y);
	}
}
void st(){
	for(int j=1;j<=20;j++){
		for(int y=1;y<=n;y++){
			zd[y][j]=max(zd[y][j-1],zd[f[y][j-1]][j-1]);
			if(zd[y][j-1]==zd[f[y][j-1]][j-1]){
				cd[y][j]=max(cd[y][j-1],cd[f[y][j-1]][j-1]);
			}else if(zd[y][j-1]>zd[f[y][j-1]][j-1]){
				cd[y][j]=max(cd[y][j-1],zd[f[y][j-1]][j-1]);
			}else if(zd[y][j-1]<zd[f[y][j-1]][j-1]){
				cd[y][j]=max(zd[y][j-1],cd[f[y][j-1]][j-1]);
			}
			f[y][j]=f[f[y][j-1]][j-1];
		}
	}
}
void getlca(int x,int y){
	ns1=-1,ns2=-2;
	if(h[x]<h[y]){
		swap(x,y);
	}
	for(int i=20;i>=0;i--){
		if(h[f[x][i]]>=h[y]){
			if(zd[x][i]>ns1){
				ns2=ns1;
				ns1=zd[x][i];
			}
			ns2=max(ns2,cd[x][i]);
			x=f[x][i];
		}
	}
	if(x==y){
		return;
	}for(int i=20;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			if(zd[x][i]==zd[y][i]){
				ns2=ns1;
				ns1=zd[x][i];
				ns2=max(ns2,max(cd[x][i],cd[y][i]));
			}else if(zd[x][i]>zd[y][i]){
				if(zd[x][i]>ns1){
					ns2=max(ns1,zd[y][i]);
					ns1=zd[x][i];
					ns2=max(ns2,cd[x][i]);
				}else{
					ns2=max(ns2,zd[x][i]);
				}
			}else if(zd[y][i]>zd[x][i]){
				if(zd[y][i]>ns1){
					ns2=max(ns1,zd[x][i]);
					ns1=zd[y][i];
					ns2=max(ns2,cd[y][i]);
				}else{
					ns2=max(ns2,zd[y][i]);
				}
			}
			x=f[x][i];
			y=f[y][i];
		}
		
	}
	
	if(zd[x][0]==zd[y][0]){
		ns2=ns1;
		ns1=zd[x][0];
		ns2=max(ns2,max(cd[x][0],cd[y][0]));
	}else if(zd[x][0]>zd[y][0]){
		if(zd[x][0]>ns1){
			ns2=max(ns1,zd[y][0]);
			ns1=zd[x][0];
			ns2=max(ns2,cd[x][0]);
		}else{
			ns2=max(ns2,zd[x][0]);
		}
	}else if(zd[y][0]>zd[x][0]){
		if(zd[y][0]>ns1){
			ns2=max(ns1,zd[x][0]);
			ns1=zd[y][0];
			ns2=max(ns2,cd[y][0]);
		}else{
			ns2=max(ns2,zd[y][0]);
		}
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		if(x==y){
            continue;
        }m1++;
		eg[m1].u=x;
		eg[m1].v=y;
		eg[m1].w=z;
	}	
	sort(eg+1,eg+m1+1,cmp);
	for(int i=1;i<=n;i++){
		r[i]=i;
	}int cnt=0;
	int s=0,ans=0x3f3f3f3f3f3f3f3f;
	for(int i=1;i<=m1;++i){
		int x=getf(eg[i].u),y=getf(eg[i].v);
		if(x!=y){
			r[y]=x;
			adg(eg[i].u,eg[i].v,eg[i].w);
			adg(eg[i].v,eg[i].u,eg[i].w);
			s+=eg[i].w;
			eg[i].fg=1;
			cnt++; 
			if(cnt==n-1){
				break;
			}
		}
	}
	memset(cd,-1,sizeof(cd));
	h[1]=1;
	f[1][0]=0;
	zd[1][0]=0;
	cd[1][0]=-1;
	dfs(1);
	st();
	for(int i=1;i<=m1;i++){
		if(eg[i].fg==1){
			continue;
		}getlca(eg[i].u,eg[i].v);
		if(eg[i].w>ns1){
			int tnt=s-ns1+eg[i].w;
			ans=min(ans,tnt);
		}else if(eg[i].w==ns1){
			if(ns2==-1){
				continue;
			}int tnt=s-ns2+eg[i].w;
			ans=min(ans,tnt);
		}
	}
	cout<<ans<<endl; 
}
  • 平面最近点对(加强版)
    乱搞可做
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define pii pair<int,int>
bool cmp(pii a,pii b){
    return a.first*a.second<b.first*b.second;
}
pii a[514514];
int maxx[514514];
signed main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
        cin>>a[i].first>>a[i].second;
        maxx[i]=min(n,i+850);
    }
    int ans=1e17;
	sort(a+1,a+n+1,cmp);
	n=unique(a+1,a+n+1)-a-1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=maxx[i];j++){
			int tx=a[i].first-a[j].first;
            int ty=a[i].second-a[j].second;
			if(tx*tx+ty*ty<ans){
                ans=tx*tx+ty*ty;
            }
		}
    }
	cout<<fixed<<setprecision(3)<<sqrt(ans)<<endl;
} 
  • 乒乓球(done)黄
  • 消失之物(done)橙

9.30

  • [NOIP2015 提高组] 子串(done)
    很好的dp,非常不错的练手题
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[1145][1145][2];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    string a,b;
    cin>>a>>b;
    a=' '+a,b=' '+b;
    dp[0][0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=m;j;j--){
            for(int p=1;p<=k;p++){
                if(a[i]==b[j]){
                    dp[j][p][0]=dp[j][p][0]+dp[j][p][1];
                    dp[j][p][1]=(dp[j-1][p][1]+dp[j-1][p-1][1])%1000000007+dp[j-1][p-1][0];
                }else{
                    dp[j][p][0]=dp[j][p][0]+dp[j][p][1];
                    dp[j][p][1]=0;
                }
                dp[j][p][0]%=1000000007;
                dp[j][p][1]%=1000000007;
            }
        }
    }
    cout<<(dp[m][k][1]+dp[m][k][0])%1000000007<<endl;
}

首先这道题肯定是 $O(nmk)$ 的时间复杂度, $k$ 在这里很好理解是个啥,那么就有个显而易见的dp:

考虑枚举目前是第几个子串,上一个子串覆盖到B串的哪里,然后就可以枚举怎么选了

这里循环顺序需要注意是先枚举目前在A串中的位置,然后再枚举覆盖到哪了,最后枚举第几个子串

考虑每个点选与不选,那么有\(A_i = B_j\)时才能够更新选的状态,否则为上一个推过来,那么dp方程很明显了awa

  • GCD(done)
    数论大作战
    我了个5分钟造完数据啊

    考虑直接暴力,可以得分:40

    好,喜喜爱抚标准暴力分,很有精神

    考虑到这玩意gcd为质数,那就很棒了,那么只需要对于每个 \(x=p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*……*p_q^{k_q}\) 找出一个 \(y\) 满足 \(y=p_j*任意一个不为x的因子的素数\) 即可,反过来就是对于所有小于 \(n\) 的素数吃吃吃,看能找出多少个不整除 \(n\) 的素数吃吃吃即可

    #define 吃吃吃 统计答案

  • 【模板】manacher算法(done)
    板子,核心思路是从一个点扩展

  • [eJOI2019] 异或橙子(done)
    树状数组维护奇偶性分讨即可

  • 飞扬的小鸟(done)
    好恶心的dp,需要注意边界条件和上一次从哪里出到这根管子的哪里,但是大体较为简单

10.1

  • [CSP-S2019] 划分
    猎奇贪心高精+十字相乘求贡献,骇死我力
    贪心+单调队列优化枚举即可,实则难在猎奇高精度和拆拆比
  • 猜数字
    神秘结论题,轻输入文本
code
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1145],b[1145];
int x,y;		
void exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return ;
	}
	exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
}
int qmul(int a,int b,int mod){
	int ans=0;
	while(b){
		if(b&1){
			ans+=a;
			ans%=mod;
		}b>>=1;
        a*=2;
        a%=mod;
	}
	return ans;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
        cin>>b[i];
	}
	int s=1;
	int ans=0;
	for(int i=1;i<=n;i++){
		s*=b[i];
    }
	for(int i=1;i<=n;i++){
		int t=s/b[i];
		exgcd(t,b[i],x,y);
		if(a[i]<0){
			a[i]=b[i]+(a[i]%b[i]);
		}
		ans=((ans+qmul(qmul((t%s)+s,(x%s)+s,s)%s,(a[i]%s),s))%s+s)%s;
	}
	cout<<ans<<endl;
 } 
  • [HNOI2013] 消毒
    我是绿皮我厉害,我能寻思很多东西
    对于一块东西,我们肯定是拆成行和列更优,而遇到了一坨东西,肯定是正方形最优,所以实际上变成了正方形大赛
    然后后面就是可爱的二分图操作,但是我不会
  • [USACO08FEB] Hotel G
    \珂朵莉/\珂朵莉/\珂朵莉/
    这期神了,平推树模板题,考虑维护空段,则每个空段在插入操作时一定是头部被插入然后分裂两个空段,而加入操作视为合并水过去即可
  • 明明的随机数
    橙
  • 序列终结者
    真的不是平衡树板子吗?

10.2~10.6:

右转国庆总结

10.7

补作业

10.8~10

whk测试,whk测试,还是whk测试

10.11

滚去打ybtoj+xyd的模考了

10.12

补题

10.13

  • [USACO06NOV] 玉米田
    暴力状压dp即可,很水的练手题
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[15][11451];
int a[1145][1145];
int p[1145];
signed main(){
	memset(dp,0,sizeof(dp));
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			p[i]*=2;
			p[i]+=a[i][j];
		}
	}dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=(1<<m+1)-1;j++){
			for(int k=0;k<=(1<<m+1);k++){
				if(k&j||k&(k<<1)||(k|p[i])!=p[i]){
					continue;
				}dp[i][k]+=dp[i-1][j];
				dp[i][k]%=100000000;
			}
		}
	}int anss=0;
	for(int i=0;i<=(1<<m+1)-1;i++){
		anss+=dp[n][i];
		anss%=100000000;
	}cout<<anss<<endl;
}

珍爱生命,远离异或判子集(会导致只有集合 \(=\) 目标集合时才有共享)

  • [ZJOI2015] 幻想乡战略游戏
    拿到题目貌似是带权重心耶owo
    首先考虑贪心,如果这个地方加入了军队,那么考虑慢慢向其移动,否则向其反方向军营数量最多的方向移动owo
    能拿20分!
    如果加上贪心……
    还是20分(悲)
    我们考虑动态维护带权子树重,则有动态淀粉质的做法,但是太难了,我不会,怎么办?
    首先考虑雷霆贪心,我们肯定是将重心向最重的那颗子树走,那么我们可以优化部分移动
    又有跳跃可以用树链剖分+三分(因为这个答案在这条贡献链上一定是有单调最低点的),那就可以维护这么一大坨东西来拿到80分
    然后考虑动态维护怎么求权值,可以用一个主席树维护修改(因为加入删除军队都几乎影响了一条链而非子树,并且要求能推到子树那么说明需要维护以前的版本)
    \(O(n \log^5 n)\),啥东西啊
  • 运动员最佳匹配问题
    我说好的状压dp呢qwq,怎么搜到你了啊!
    这玩意是个雷霆记忆化搜索给我气死了
  • Koishi Loves Segments
    纯粹的贪心,都不需要什么线段树这种高端玩意,直接口胡个multiset水过去即可
  • 小书童——凯撒密码
    红题秒了

10.14

  • [HNOI2015] 开店
  • 洗牌
  • [TJOI2014] 匹配
    二分图上费用流
  • 小B的询问
  • 数字反转(升级版)
    橙题

10.15

  • 有线电视网
    树形dp入门题,dp状态设计二维即可,分别表示选到第k个节点和是否选择,空间复杂 \(O(n)\) 时间复杂 \((nm)\)

  • 荒岛野人
    我不要写数论啊qwq
    考虑对于这坨野人
    没有相遇不就是考虑减去相遇的方案吗……
    然后就是 \(O(n^2m)\)次青蛙的约会……

  • 丘比特的烦恼
    带权二分图最大匹配没啥好说的

  • [国家集训队] 小Z的袜子
    莫队板子,味大,无需多盐
    考虑排序每个问题的左端点,然后拓展即可

  • [USACO1.1] 你的飞碟在这儿
    水题,刷着玩的

    顺便复习了tarjan的板子和线段树的板子

10.16

  • [Ynoi Easy Round 2016] 掉进兔子洞
  • 二叉苹果树
  • [AHOI2005] 约数研究
  • [SDOI2006] 仓库管理员的烦恼
  • [国家集训队] 数颜色 / 维护队列
  • 计数问题

10.17

  • [ZJOI2007] 时态同步
  • 倒酒
  • [NOI2011] 兔兔与蛋蛋游戏
  • Count on a tree
  • 级数求和

10.18

  • [ZJOI2006] 三色二叉树
  • [CQOI2007] 余数求和
  • [JSOI2009] 游戏
  • 【模板】重链剖分/树链剖分
  • [USACO1.5] 回文质数 Prime Palindromes

10.19

  • [NOIP2003 提高组] 加分二叉树
  • [SDOI2008] 沙拉公主的困惑
  • [HEOI2016/TJOI2016] 游戏
  • 【模板】普通平衡树
  • 津津的储蓄计划

10.20

  • [SDOI2010] 地精部落
  • [HAOI2011] Problem b
  • [BJOI2012] 连连看
  • 【模板】左偏树(可并堆)
  • 买铅笔

10.21

  • 选数
  • 【模板】动态树(LCT)
  • 分配问题
  • 寒假作业
  • 颜色平衡树
  • 天际线

10.22

  • 多米诺骨牌
  • 能量采集
  • 运动员最佳匹配问题
  • 【模板】三维偏序(陌上花开)
  • [USACO1.3] 混合牛奶 Mixing Milk

10.23

  • [NOIP2006 提高组] 金明的预算方案
  • Problem b
  • 二分图最大权完美匹配
  • Tree
  • 纪念品分组

10.24

  • 重建道路
  • 公约数的和
  • [FJOI2015] 火星商店问题
  • 【模板】莫队二次离线 / 第十四分块
  • 作诗
  • 排队接水

10.25(窝的生日)

  • [CTSC1997] 选课
  • 约数个数和
  • [SDOI2017] 新生舞会
  • [AHOI2005] 航线规划
  • 凌乱的yyy / 线段覆盖

10.26

  • 木棍加工
  • 数表
  • [TJOI2014] 匹配
  • [USACO03FALL] Beauty Contest G / 【模板】旋转卡壳
  • 合并果子

10.27

  • [HAOI2009] 逆序对数列
  • [NOI2014] 魔法森林
  • [SDOI2006] 仓库管理员的烦恼
  • [USACO5.1] 圈奶牛Fencing the Cows / 【模板】二维凸包
  • 数列分段 Section II

10.28

  • [HAOI2006] 数字序列
  • [BJOI2012] 连连看
  • 【模板】自适应辛普森法1
  • 一元三次方程求解

10.29

  • [NOIP2007 提高组] 矩阵取数游戏
  • [SDOI2009] SuperGCD
  • [省选联考 2021 A 卷] 支配
  • 【模板】nim游戏
  • 砍树

10.30

  • [SCOI2009] 粉刷匠
  • [HNOI2011] 卡农
  • 最长不下降子序列问题
  • [HNOI2007] 分裂游戏
  • [NOIP2015 提高组] 跳石头
  • [CSP-S 2022] 星战

------------恢复内容开始------------

如果出现模考,优先模考

然后周末补掉没做的(

9.29

  • [CSP-S2019] Emiya 家今天的饭(done)
    由于直接计算可行方案数难度不亚于切黑,所以直接通过正难则反,将这道题变成求所有不合法的方案数,然后求助对于全部方案数减去这些方案即可

考虑不合法的状态,发现只需要枚举是哪种食材出现次数超过 \(\frac{k}{2}\) 即可,然后就是简单的枚举+dp

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[114][5141],dp[114][5145];
int cnt[1145];
signed main(){
    int ans=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            cnt[i]=(cnt[i]+a[i][j])%998244353;
        }
        ans*=(cnt[i]+1)%998244353;
        ans%=998244353;
    }
    ans+=998244352;
    ans%=998244353;
	for(int i=1;i<=m;i++){
		memset(dp,0,sizeof(dp));
		dp[0][0]=1;
		for(int j=1;j<=n;j++)
			for(int k=0;k<=2*(j-1);k++){
				dp[j][k]=(dp[j][k]+dp[j-1][k]*(cnt[j]-a[j][i]))%998244353;
				dp[j][k+1]=(dp[j][k+1]+dp[j-1][k])%998244353;
				dp[j][k+2]=(dp[j][k+2]+dp[j-1][k]*a[j][i])%998244353;
			}
		for(int j=n+1;j<=2*n;j++){
            ans=(ans+998244353-dp[n][j])%998244353;
        }
	}
    cout<<ans<<endl;
}
  • [SHOI2009] 会场预约(done)
    这不是优先队列板子题吗
    你可以考虑线段树维护,但是又臭又长没必要
    考虑使用我们伟大的stl库针对set同志给出的upperbound然后就可以轻松愉快的解决了!
  • [BJWC2010] 严格次小生成树(done)
    考虑对于环上的点,直接倍增找到一个环上最小的边然后替换,有一个性质是最小生成树上的边换成环上次小的边能变成非严格次小生成树,所以就有了次小生成树最小为严格次小生成树
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
	int u,v,w,pre;
	bool fg;
};
node eg[1145141],b[1145141];
int n,m,m1=0,k,head[1145141],f[1145141][22],h[1145141],zd[1145141][22],cd[1145141][22],r[1145141];
int ns1,ns2;
bool cmp(node x,node y){
	return x.w<y.w;
}
int getf(int x){
	if(x!=r[x])
		r[x]=getf(r[x]);
	return r[x];
}
void adg(int x,int y,int z){
	k++;
	b[k].v=y;
	b[k].w=z;
	b[k].pre=head[x];
	head[x]=k;
}
void dfs(int x){
	for(int i=head[x];i;i=b[i].pre){
		int y=b[i].v;
		if(h[y]){
			continue;
		}h[y]=h[x]+1;
		f[y][0]=x;
		zd[y][0]=b[i].w;
		cd[y][0]=-1;
		dfs(y);
	}
}
void st(){
	for(int j=1;j<=20;j++){
		for(int y=1;y<=n;y++){
			zd[y][j]=max(zd[y][j-1],zd[f[y][j-1]][j-1]);
			if(zd[y][j-1]==zd[f[y][j-1]][j-1]){
				cd[y][j]=max(cd[y][j-1],cd[f[y][j-1]][j-1]);
			}else if(zd[y][j-1]>zd[f[y][j-1]][j-1]){
				cd[y][j]=max(cd[y][j-1],zd[f[y][j-1]][j-1]);
			}else if(zd[y][j-1]<zd[f[y][j-1]][j-1]){
				cd[y][j]=max(zd[y][j-1],cd[f[y][j-1]][j-1]);
			}
			f[y][j]=f[f[y][j-1]][j-1];
		}
	}
}
void getlca(int x,int y){
	ns1=-1,ns2=-2;
	if(h[x]<h[y]){
		swap(x,y);
	}
	for(int i=20;i>=0;i--){
		if(h[f[x][i]]>=h[y]){
			if(zd[x][i]>ns1){
				ns2=ns1;
				ns1=zd[x][i];
			}
			ns2=max(ns2,cd[x][i]);
			x=f[x][i];
		}
	}
	if(x==y){
		return;
	}for(int i=20;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			if(zd[x][i]==zd[y][i]){
				ns2=ns1;
				ns1=zd[x][i];
				ns2=max(ns2,max(cd[x][i],cd[y][i]));
			}else if(zd[x][i]>zd[y][i]){
				if(zd[x][i]>ns1){
					ns2=max(ns1,zd[y][i]);
					ns1=zd[x][i];
					ns2=max(ns2,cd[x][i]);
				}else{
					ns2=max(ns2,zd[x][i]);
				}
			}else if(zd[y][i]>zd[x][i]){
				if(zd[y][i]>ns1){
					ns2=max(ns1,zd[x][i]);
					ns1=zd[y][i];
					ns2=max(ns2,cd[y][i]);
				}else{
					ns2=max(ns2,zd[y][i]);
				}
			}
			x=f[x][i];
			y=f[y][i];
		}
		
	}
	
	if(zd[x][0]==zd[y][0]){
		ns2=ns1;
		ns1=zd[x][0];
		ns2=max(ns2,max(cd[x][0],cd[y][0]));
	}else if(zd[x][0]>zd[y][0]){
		if(zd[x][0]>ns1){
			ns2=max(ns1,zd[y][0]);
			ns1=zd[x][0];
			ns2=max(ns2,cd[x][0]);
		}else{
			ns2=max(ns2,zd[x][0]);
		}
	}else if(zd[y][0]>zd[x][0]){
		if(zd[y][0]>ns1){
			ns2=max(ns1,zd[x][0]);
			ns1=zd[y][0];
			ns2=max(ns2,cd[y][0]);
		}else{
			ns2=max(ns2,zd[y][0]);
		}
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y,z;
		cin>>x>>y>>z;
		if(x==y){
            continue;
        }m1++;
		eg[m1].u=x;
		eg[m1].v=y;
		eg[m1].w=z;
	}	
	sort(eg+1,eg+m1+1,cmp);
	for(int i=1;i<=n;i++){
		r[i]=i;
	}int cnt=0;
	int s=0,ans=0x3f3f3f3f3f3f3f3f;
	for(int i=1;i<=m1;++i){
		int x=getf(eg[i].u),y=getf(eg[i].v);
		if(x!=y){
			r[y]=x;
			adg(eg[i].u,eg[i].v,eg[i].w);
			adg(eg[i].v,eg[i].u,eg[i].w);
			s+=eg[i].w;
			eg[i].fg=1;
			cnt++; 
			if(cnt==n-1){
				break;
			}
		}
	}
	memset(cd,-1,sizeof(cd));
	h[1]=1;
	f[1][0]=0;
	zd[1][0]=0;
	cd[1][0]=-1;
	dfs(1);
	st();
	for(int i=1;i<=m1;i++){
		if(eg[i].fg==1){
			continue;
		}getlca(eg[i].u,eg[i].v);
		if(eg[i].w>ns1){
			int tnt=s-ns1+eg[i].w;
			ans=min(ans,tnt);
		}else if(eg[i].w==ns1){
			if(ns2==-1){
				continue;
			}int tnt=s-ns2+eg[i].w;
			ans=min(ans,tnt);
		}
	}
	cout<<ans<<endl; 
}
  • 平面最近点对(加强版)
    乱搞可做
code
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define pii pair<int,int>
bool cmp(pii a,pii b){
    return a.first*a.second<b.first*b.second;
}
pii a[514514];
int maxx[514514];
signed main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
        cin>>a[i].first>>a[i].second;
        maxx[i]=min(n,i+850);
    }
    int ans=1e17;
	sort(a+1,a+n+1,cmp);
	n=unique(a+1,a+n+1)-a-1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=maxx[i];j++){
			int tx=a[i].first-a[j].first;
            int ty=a[i].second-a[j].second;
			if(tx*tx+ty*ty<ans){
                ans=tx*tx+ty*ty;
            }
		}
    }
	cout<<fixed<<setprecision(3)<<sqrt(ans)<<endl;
} 
  • 乒乓球(done)黄
  • 消失之物(done)橙

9.30

  • [NOIP2015 提高组] 子串(done)
    很好的dp,非常不错的练手题
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[1145][1145][2];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    string a,b;
    cin>>a>>b;
    a=' '+a,b=' '+b;
    dp[0][0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=m;j;j--){
            for(int p=1;p<=k;p++){
                if(a[i]==b[j]){
                    dp[j][p][0]=dp[j][p][0]+dp[j][p][1];
                    dp[j][p][1]=(dp[j-1][p][1]+dp[j-1][p-1][1])%1000000007+dp[j-1][p-1][0];
                }else{
                    dp[j][p][0]=dp[j][p][0]+dp[j][p][1];
                    dp[j][p][1]=0;
                }
                dp[j][p][0]%=1000000007;
                dp[j][p][1]%=1000000007;
            }
        }
    }
    cout<<(dp[m][k][1]+dp[m][k][0])%1000000007<<endl;
}

首先这道题肯定是 $O(nmk)$ 的时间复杂度, $k$ 在这里很好理解是个啥,那么就有个显而易见的dp:

考虑枚举目前是第几个子串,上一个子串覆盖到B串的哪里,然后就可以枚举怎么选了

这里循环顺序需要注意是先枚举目前在A串中的位置,然后再枚举覆盖到哪了,最后枚举第几个子串

考虑每个点选与不选,那么有\(A_i = B_j\)时才能够更新选的状态,否则为上一个推过来,那么dp方程很明显了awa

  • GCD(done)
    数论大作战
    我了个5分钟造完数据啊
    考虑直接暴力,可以得分:40
    好,喜喜爱抚标准暴力分,很有精神
    考虑到这玩意gcd为质数,那就很棒了,那么只需要对于每个 \(x=p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*……*p_q^{k_q}\) 找出一个 \(y\) 满足 \(y=p_j*任意一个不为x的因子的素数\) 即可,反过来就是对于所有小于 \(n\) 的素数吃吃吃,看能找出多少个不整除 \(n\) 的素数吃吃吃即可
    #define 吃吃吃 统计答案

  • 【模板】manacher算法(done)
    板子,核心思路是从一个点扩展

  • [eJOI2019] 异或橙子(done)
    树状数组维护奇偶性分讨即可

  • 飞扬的小鸟(done)
    好恶心的dp,需要注意边界条件和上一次从哪里出到这根管子的哪里,但是大体较为简单

10.1

  • [CSP-S2019] 划分
    猎奇贪心高精+十字相乘求贡献,骇死我力
    贪心+单调队列优化枚举即可,实则难在猎奇高精度和拆拆比
  • 猜数字
    神秘结论题,轻输入文本
code
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1145],b[1145];
int x,y;		
void exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return ;
	}
	exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
}
int qmul(int a,int b,int mod){
	int ans=0;
	while(b){
		if(b&1){
			ans+=a;
			ans%=mod;
		}b>>=1;
        a*=2;
        a%=mod;
	}
	return ans;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
        cin>>b[i];
	}
	int s=1;
	int ans=0;
	for(int i=1;i<=n;i++){
		s*=b[i];
    }
	for(int i=1;i<=n;i++){
		int t=s/b[i];
		exgcd(t,b[i],x,y);
		if(a[i]<0){
			a[i]=b[i]+(a[i]%b[i]);
		}
		ans=((ans+qmul(qmul((t%s)+s,(x%s)+s,s)%s,(a[i]%s),s))%s+s)%s;
	}
	cout<<ans<<endl;
 } 
  • [HNOI2013] 消毒
    我是绿皮我厉害,我能寻思很多东西
    对于一块东西,我们肯定是拆成行和列更优,而遇到了一坨东西,肯定是正方形最优,所以实际上变成了正方形大赛
    然后后面就是可爱的二分图操作,但是我不会
  • [USACO08FEB] Hotel G
    \珂朵莉/\珂朵莉/\珂朵莉/
    这期神了,平推树模板题,考虑维护空段,则每个空段在插入操作时一定是头部被插入然后分裂两个空段,而加入操作视为合并水过去即可
  • 明明的随机数
    橙
  • 序列终结者
    真的不是平衡树板子吗?

10.2~10.6:

右转国庆总结

10.7

补作业

10.8~10

whk测试,whk测试,还是whk测试

10.11

滚去打ybtoj+xyd的模考了

10.12

补题

10.13

  • [USACO06NOV] 玉米田
    暴力状压dp即可,很水的练手题
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[15][11451];
int a[1145][1145];
int p[1145];
signed main(){
	memset(dp,0,sizeof(dp));
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			p[i]*=2;
			p[i]+=a[i][j];
		}
	}dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=(1<<m+1)-1;j++){
			for(int k=0;k<=(1<<m+1);k++){
				if(k&j||k&(k<<1)||(k|p[i])!=p[i]){
					continue;
				}dp[i][k]+=dp[i-1][j];
				dp[i][k]%=100000000;
			}
		}
	}int anss=0;
	for(int i=0;i<=(1<<m+1)-1;i++){
		anss+=dp[n][i];
		anss%=100000000;
	}cout<<anss<<endl;
}

珍爱生命,远离异或判子集(会导致只有集合 \(=\) 目标集合时才有共享)

  • [ZJOI2015] 幻想乡战略游戏
    拿到题目貌似是带权重心耶owo
    首先考虑贪心,如果这个地方加入了军队,那么考虑慢慢向其移动,否则向其反方向军营数量最多的方向移动owo
    能拿20分!
    如果加上贪心……
    还是20分(悲)
    我们考虑动态维护带权子树重,则有动态淀粉质的做法,但是太难了,我不会,怎么办?
    首先考虑雷霆贪心,我们肯定是将重心向最重的那颗子树走,那么我们可以优化部分移动
    又有跳跃可以用树链剖分+三分(因为这个答案在这条贡献链上一定是有单调最低点的),那就可以维护这么一大坨东西来拿到80分
    然后考虑动态维护怎么求权值,可以用一个主席树维护修改(因为加入删除军队都几乎影响了一条链而非子树,并且要求能推到子树那么说明需要维护以前的版本)
    \(O(n \log^5 n)\),啥东西啊
  • 运动员最佳匹配问题
    我说好的状压dp呢qwq,怎么搜到你了啊!
    这玩意是个雷霆记忆化搜索给我气死了
  • Koishi Loves Segments
    纯粹的贪心,都不需要什么线段树这种高端玩意,直接口胡个multiset水过去即可
  • 小书童——凯撒密码
    红题秒了

10.14

  • [HNOI2015] 开店
    不会,待想
  • 洗牌
  • [TJOI2014] 匹配
    二分图上费用流,套了个之前写的DINIC过了
  • 小B的询问
    莫队板子
    首先每个区间的答案一定可以通过一段大的区间减去小的区间的贡献来求出,即 \([l~r]\) 的贡献一定可以用 \([1,l-1]\) 与 \([1,r]\) 得出
    那这玩意就是纯粹的莫队,对左端点排序然后简单统计即可
  • 数字反转(升级版)
    橙题

10.15

  • 有线电视网
  • 荒岛野人
  • 丘比特的烦恼
  • [国家集训队] 小Z的袜子
  • [USACO1.1] 你的飞碟在这儿

10.16

  • [Ynoi Easy Round 2016] 掉进兔子洞
  • 二叉苹果树
  • [AHOI2005] 约数研究
  • [SDOI2006] 仓库管理员的烦恼
  • [国家集训队] 数颜色 / 维护队列
  • 计数问题

10.17

  • [ZJOI2007] 时态同步
  • 倒酒
  • [NOI2011] 兔兔与蛋蛋游戏
  • Count on a tree
  • 级数求和

10.18

  • [ZJOI2006] 三色二叉树
  • [CQOI2007] 余数求和
  • [JSOI2009] 游戏
  • 【模板】重链剖分/树链剖分
  • [USACO1.5] 回文质数 Prime Palindromes

10.19

  • [NOIP2003 提高组] 加分二叉树
  • [SDOI2008] 沙拉公主的困惑
  • [HEOI2016/TJOI2016] 游戏
  • 【模板】普通平衡树
  • 津津的储蓄计划

10.20

  • [SDOI2010] 地精部落
  • [HAOI2011] Problem b
  • [BJOI2012] 连连看
  • 【模板】左偏树(可并堆)
  • 买铅笔

10.21

  • 选数
  • 【模板】动态树(LCT)
  • 分配问题
  • 寒假作业
  • 颜色平衡树
  • 天际线

10.22

  • 多米诺骨牌
  • 能量采集
  • 运动员最佳匹配问题
  • 【模板】三维偏序(陌上花开)
  • [USACO1.3] 混合牛奶 Mixing Milk

10.23

  • [NOIP2006 提高组] 金明的预算方案
  • Problem b
  • 二分图最大权完美匹配
  • Tree
  • 纪念品分组

10.24

  • 重建道路
  • 公约数的和
  • [FJOI2015] 火星商店问题
  • 【模板】莫队二次离线 / 第十四分块
  • 作诗
  • 排队接水

10.25(窝的生日)

  • [CTSC1997] 选课
  • 约数个数和
  • [SDOI2017] 新生舞会
  • [AHOI2005] 航线规划
  • 凌乱的yyy / 线段覆盖

10.26

  • 木棍加工
  • 数表
  • [TJOI2014] 匹配
  • [USACO03FALL] Beauty Contest G / 【模板】旋转卡壳
  • 合并果子

10.27

  • [HAOI2009] 逆序对数列
  • [NOI2014] 魔法森林
  • [SDOI2006] 仓库管理员的烦恼
  • [USACO5.1] 圈奶牛Fencing the Cows / 【模板】二维凸包
  • 数列分段 Section II

10.28

  • [HAOI2006] 数字序列
  • [BJOI2012] 连连看
  • 【模板】自适应辛普森法1
  • 一元三次方程求解

10.29

  • [NOIP2007 提高组] 矩阵取数游戏
  • [SDOI2009] SuperGCD
  • [省选联考 2021 A 卷] 支配
  • 【模板】nim游戏
  • 砍树

10.30

  • [SCOI2009] 粉刷匠
  • [HNOI2011] 卡农
  • 最长不下降子序列问题
  • [HNOI2007] 分裂游戏
  • [NOIP2015 提高组] 跳石头
  • [CSP-S 2022] 星战

------------恢复内容结束------------

posted @ 2026-09-14 18:44  ALPHA_wule  阅读(25)  评论(0)    收藏  举报