2021/7/7——集训Day.2

昨天晚上还是日常失眠

夜里还听到类似猫叫的声音

按照寝室的值日规划——一人值两天,我完事儿了

早上只吃了两颗煮鸡蛋就来机房了,还没开门,等了一会儿gzx大佬才来,虽然门口也有郑外的在等,但根本没说上话

我以为外校来的第一天就应该建好个小群,拉进每个学校一个人,然后像并查集一样所有人都进来,但是现在基本上都没有怎么说过话

太原五中的还是没有来,jyh学长请我吃的粽子我都没给钱,到时候让他的学弟/学妹带过去吧

闲话少说,上了个撤硕就开始看题了P4768 [NOI2018] 归程啧啧啧的题解啧啧啧
至于解,我在昨天的博客里已经口胡过了,所以就直接代码怼脸喽

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
int n,m,q,k,s,cnt,ans,a,b,c,d,num,tot,shen[N],hh[N],fa[N],bj[N][20],T;bool flag[N];
struct node{int hd,Next,ver;}tr[N<<1];
struct ao{int x,y,z,a;}o[N<<1];
struct eo{int Next,ver,hd,edge;}e[N<<1];
struct Node{int a,v;}p[N];
void add1(int x,int y,int z){e[++tot].ver=y;e[tot].Next=e[x].hd;e[x].hd=tot;e[tot].edge=z;}
void add(int x,int y){tr[++tot].ver=y;tr[tot].Next=tr[x].hd;tr[x].hd=tot;}
void dijkstra()
{
	priority_queue<pair<int,int> > q;
	memset(hh,100,sizeof hh);memset(flag,0,sizeof flag);
	q.push(make_pair(0,1));hh[1]=0;
	while(q.size())
	{
		int x=q.top().second;q.pop();
		if(flag[x])continue;
		flag[x]=1;
		for(int i=e[x].hd;i;i=e[i].Next)
		{
			int y=e[i].ver,z=e[i].edge;
			if(hh[y]>hh[x]+z){hh[y]=hh[x]+z;q.push(make_pair(-hh[y],y));}
		}
	}
	for(int i=1;i<=n;i++)p[i].v=hh[i];
}
void dfs(int x,int f)
{
	shen[x]=shen[f]+1;bj[x][0]=f;
	for(int i=1;i<=19;i++)bj[x][i]=bj[bj[x][i-1]][i-1];
	for(int i=tr[x].hd;i;i=tr[i].Next)
	{
		int y=tr[i].ver;
		dfs(y,x);p[x].v=min(p[x].v,p[y].v);
	}
}
int ask(int x,int y)
{
	for(int i=19;i>=0;i--)if(bj[x][i]&&p[bj[x][i]].a>y)x=bj[x][i];
	ans=p[x].v;return ans;
}
int get(int x)
{
	if(x==fa[x])return x;
	return fa[x]=get(fa[x]);
}
bool mycmp(ao x,ao y){return x.a>y.a;}
void kruskal()
{
	sort(o+1,o+m+1,mycmp);
	cnt=n;tot=0;num=0;
	for(int i=1;i<=m;i++)
	{
		int fx=get(o[i].x),fy=get(o[i].y);
		if(fx!=fy)
		{
			add(++cnt,fx);add(cnt,fy);
			fa[fx]=cnt;fa[fy]=cnt;p[cnt].a=o[i].a;num++;
		}
		if(num==n-1)break;
	}
	dfs(cnt,0);
	while(q--)
	{
		int x,y;scanf("%d%d",&x,&y);
		x=(x+k*ans-1)%n+1;y=(y+k*ans)%(s+1);ans=ask(x,y);
		printf("%d\n",ans);
	}
}
int main()
{freopen("return.in", "r", stdin);freopen("return.out", "w", stdout);
	scanf("%d",&T);
	while(T--)
	{
		ans=0;cnt=tot=0;scanf("%d%d",&n,&m);
		memset(e,0,sizeof e);memset(bj,0,sizeof bj);memset(shen,0,sizeof shen);memset(tr,0,sizeof tr);
		for(int i=1;i<=(n<<1);i++)fa[i]=i;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&a,&b,&c,&d);
			o[i]=(ao){a,b,c,d};add1(a,b,c);add1(b,a,c);
		}
		dijkstra();
		for(int i=n+1;i<=(n<<1);i++)p[i].v=2147483645;
		scanf("%d%d%d",&q,&k,&s);
		kruskal();
	}
	return 0;
}

一开始不是p[i].v=2147483645;,由于初始值太小,在洛谷上还WA了两组数据
然后就听jjh大佬口胡,下课看他和女朋友卿卿我我,然后中午吃过饭就回来机房
中午吃的可乐鸡,鸡块的小骨头渣扎得我嘴里面烂的地方,巨疼,差点疼哕出来,自闭了
看了眼排行榜,差不多快垫底了,本来想去校医那里的,只好赶紧码代码了
中午的时候才知道脸盲的jsy大佬竟然把jjh的女朋友当成了班主任,我直接笑死
看了P5459 [BJOI2016]回转寿司这个题,然后一开始感觉权值线段树已经够可以了,后来看了myf大佬的代码,太妙了,前缀和+离散化,然后搞个树状数组,我写完用了不到 30 30 30 行代码就 A A A 了,不过后来看洛谷题解有个大佬用队列维护就离谱(交代码的时候还不小心交到别的题上了一次,还因为 l o n g    l o n g long \;long longlong的问题 W A WA WA 了几发)

#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n,zuo,sl,az,ay,you,len,f[N];long long ans,qzh[N],a[N]; 
int lowbit(int x){return x&-x;}
void add(int x,int v){for(;x<=n;x+=lowbit(x))f[x]+=v;}
long long cz(long long x,long long sum)
{
	for(;x;x-=lowbit(x))sum+=f[x];
	return sum;
}
int main()
{
	scanf("%d%d%d",&n,&zuo,&you);
	for(int i=1;i<=n;i++){scanf("%lld",&qzh[i]);qzh[i]+=qzh[i-1];a[i]=qzh[i];}
	a[n+1]=0;sort(a+1,a+n+2);
	len=unique(a+1,a+2+n)-a-1;sl=lower_bound(a+1,a+len+1,0)-a;
	add(sl,1);
	for(int i=1;i<=n;i++)
	{
		az=lower_bound(a+1,a+len+1,qzh[i]-you)-a-1,ay=upper_bound(a+1,a+len+1,qzh[i]-zuo)-a-1;
		ans+=cz(ay*1ll,0*1ll)-cz(az*1ll,0*1ll);
		int linshi=lower_bound(a+1,a+len+1,qzh[i])-a;
		add(linshi,1);
	}
	cout<<ans;
	return 0;
}

然后我发现全世界只有我还没写连续攻击游戏,就赶紧去看题。看着这个题,我想起来省选的时候的那个翻牌的题。题解第一篇就是个二分图,然后还有暴搜水过去的,但是毕竟这两天集训都是数据结构,还是要搞并查集写显得比较尊重

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
int n,a,b,fa[N];bool flag[N];
int get_father(int x)
{
	if(x==fa[x])return x;
	return fa[x]=get_father(fa[x]);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n+1;i++)fa[i]=i;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a,&b);
		a=get_father(a),b=get_father(b);
		if(a==b)flag[a]=1;
		else
		{
			flag[min(a,b)]=1;
			fa[min(a,b)]=max(a,b);
		}
	}
	for(int i=1;;i++)if(!flag[i]){cout<<i-1;return 0;}
}

ps.zwj老师说先不用写博客总结,等到后面复习的时候再过
我肯定听话啊

然后高强度自闭,其实我压行就是因为

我不擅长写大码量代码

压行后就显得代码短了,心情愉悦,但是后面的题我连压的欲望都没有,直接开始学主席树去了~
其实学也不想学,开始尝试用分块水线段树,写一会儿发现更麻烦,还不如线段树
问了jkh大佬,并且看洛谷题解第一篇,终于写出了P3178 [HAOI2015]树上操作 d f s dfs dfs 序 + 线段树解法

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define N 400010
int n,m,hd[N],ver[N],nxt[N],dfn[N],shen[N],sz[N],val[N],a[N],b[N],cnt,tot,flag,x,v;
void lian(int x,int y){ver[++cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt;}
void dfs(int x)
{
	dfn[x]=++tot;sz[x]=1;
	for(int i=hd[x];i;i=nxt[i])
	{
		int y=ver[i];
		if(!sz[y]){shen[y]=shen[x]+1;dfs(y);sz[x]+=sz[y];}
	}
}
void xg(int x,int y,int zf,int yf,int p,int l,int r)
{
	if(zf<=l&&yf>=r){a[p]+=x;b[p]+=y;return;}
	a[p*2]+=a[p];a[p*2+1]+=a[p];b[p*2]+=b[p];b[p*2+1]+=b[p];a[p]=0;b[p]=0;
	int mid=(l+r)>>1;
	if(zf<=mid)xg(x,y,zf,yf,p*2,l,mid);
	if(yf>mid)xg(x,y,zf,yf,p*2+1,mid+1,r);
}
int ans(int x,int y,int p,int l,int r)
{
	if(l==r) return shen[x]*a[p]+b[p];
	a[p*2]+=a[p];a[p*2+1]+=a[p];b[p*2]+=b[p];b[p*2+1]+=b[p];a[p]=0;b[p]=0;
	int mid=(l+r)>>1;
	if(y<=mid)return ans(x,y,p*2,l,mid);
	else return ans(x,y,p*2+1,mid+1,r);
}
signed main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)scanf("%lld",&val[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%lld%lld",&x,&y);lian(x,y);lian(y,x);
	}
	shen[1]=1;dfs(1);
	for(int i=1;i<=n;i++)xg(0,val[i],dfn[i],dfn[i]+sz[i]-1,1,1,n);
	while(m--)
	{
		scanf("%lld",&flag);
		if(flag==1){scanf("%lld%lld",&x,&v);xg(0,v,dfn[x],dfn[x]+sz[x]-1,1,1,n);}
		else if(flag==2){scanf("%lld%lld",&x,&v);xg(v,-((shen[x]-1)*v),dfn[x],dfn[x]+sz[x]-1,1,1,n);}
		else{scanf("%lld",&x);printf("%lld\n",ans(x,dfn[x],1,1,n));}
	}
	return 0;
}

一开始N=100010,是 T L E TLE TLE,然后改成N=200010变成了 R E RE RE ,最后改成N=400010,终于变成了 W A WA WA,(倍增 d e b u g debug debug?)然后一生气就写上#define int long long,和signed main(),变成了 C E CE CE ,忘了改scanf了,真自闭啊。
然后继续自闭,看了会儿https://www.zhihu.com/question/267269114,又全文背诵了下《RP导论》https://wenku.baidu.com/view/c6e31028647d27284b73516f.html?from=search这里就直接写链接,不搞 M a r k d o w n Markdown Markdown了。
终于和许昌的开了个小群说话了,hyp大佬还给发了个树链剖分的好博客,%%%,不知道该存哪,就放在这里吧https://www.cnblogs.com/ivanovcraft/p/9019090.html
然后就赶紧预习 D P DP DP去了
T 1 T1 T1是个求树的直径,先随便找个“幸运观众”当根节点跑个 d f s dfs dfs ,找到最远点,然后由该点出发再跑个 d f s dfs dfs 求出离该点最远的点,就能得到树的直径了。

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
struct eo{int v,y,nxt;}e[N<<1];
int hd[N],n,tot,cun[N],ans,x,y,z,dian;
void lian(int a,int b,int c){e[++tot].y=b;e[tot].v=c;e[tot].nxt=hd[a];hd[a]=tot;}
void dfs(int x,int shen)
{
	cun[x]=1;
	if(shen>ans){ans=shen;dian=x;}
	for(int i=hd[x];i;i=e[i].nxt)if(cun[e[i].y]==0)dfs(e[i].y,shen+e[i].v);
	cun[x]=0;
}
int main()
{
	cin>>n;
	for(int i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);lian(x,y,z);lian(y,x,z);}
	dfs(1,0);ans=0;dfs(dian,0);
	printf("%d",ans);
	return 0;
} 

还蛮水的
然后老师给了个表格让写知识点的掌握情况
感觉啥都不会啊
太自闭了
发布发布,不写了,回寝室洗澡睡觉~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值