2023.3.23 日寄
2023.3.23 日寄
挑战 \(20\min\) 极限日寄+骂出题人。
越来越懒了,日寄更新频率↓/kk
一言
\(~~~~\) 在这个世界上,饱受苦难的人不一定是好人,满嘴谎话的也不一定是坏人,这个世界上有幸福存在,也有痛苦,这个世界上的绝大多数特质都可以在一个人身上共存。
\(~~~~\) 什么贪婪,自私,痛苦,压抑,短视,热情,都可以在一个人身上共存。
\(~~~~\) 还有苦难与幸福,好运与灾祸。
\(~~~~\) 人就是由这些事物所集合的存在。
\(~~~~\) 所以由我们人所组成的这个社会,它也是如此复杂的。
\(~~~~\) 无数人的祈愿在这个社会当中流转,每个人都背负着自己的祈盼在活着,痛苦的呻吟声和幸福的欢笑,每时每刻都在土地上响起。
作者:朱慈
链接:https://www.zhihu.com/question/420428840/answer/2930586287
模拟赛
\(~~~~\) 出题人你不想给分可以不给而不是把选手当狗耍。
\(~~~~\) 19/300的暴力分是个人都得流汗。还 tm 选了三道*一样长的题目。
「2021 集训队互测」序列
题意
\(~~~~\) 长为 \(n\) 的序列,每个元素都在 \([1,10^9]\) 之间。给定 \(m\) 个形如 \((i,j,k,x)\) 的信息,表示 \(a_i,a_j,a_k\) 的中位数为 \(x\)。请构造原序列或说明无解。
\(~~~~\) \(1\leq n,m\leq 10^5,1\leq x\leq 10^9\).
题解
\(~~~~\) 如果你想到了正解的算法那题目很简单,如果没想到,那一堆不知名的错解可以把你搞崩溃。
\(~~~~\) 考虑把每个数分成 \(a_i< x\) 和 \(a_i\geq x\) 两种互斥的表达式。对于一个 \((i,j,k,x)\) 的限制,显然若 \(a_i<x\) ,则必有 \(a_j \geq x,a_k\geq x\);反之若 \(a_i\geq x\),则必有 \(a_j<x+1,a_k<x+1\)
\(~~~~\) 很显然这就是一个 2-SAT 问题了,那直接套板子。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
x*=f;
}
struct node{
int p1,p2,p3,x;
node(){}
node(int P1,int P2,int P3,int X){p1=P1,p2=P2,p3=P3,x=X;}
}P[5000005];
char Ty1[15],Ty2[15];
vector <int> G[5000005];
int brr[5000005],cnt;
pair<PII,int> To[5000005];
map<int,int>M1[100005],M2[100005];//小于和大于等于
void Init(int x,int Val)
{
if(!M1[x][Val]) M1[x][Val]=++cnt,To[cnt]=mp(mp(x,Val),1);
if(!M2[x][Val+1]) M2[x][Val+1]=++cnt,To[cnt]=mp(mp(x,Val+1),2);
if(!M1[x][Val-1]) M1[x][Val-1]=++cnt,To[cnt]=mp(mp(x,Val-1),1);
if(!M2[x][Val]) M2[x][Val]=++cnt,To[cnt]=mp(mp(x,Val),2);
}
void DEBUG(int u,int v)
{
return;
int pos1=To[u].first.first,X1=To[u].first.second,Type1=To[u].second;
int pos2=To[v].first.first,X2=To[v].first.second,Type2=To[v].second;
printf("(%d%s%d) (%d%s%d)\n",pos1,Type1==1?Ty1+1:Ty2+1,X1,pos2,Type2==1?Ty1+1:Ty2+1,X2);
}
void Connect(int p1,int p2,int p3,int x)
{
if(M1[p1].count(x-1)&&M2[p2].count(x)) G[M1[p1][x-1]].push_back(M2[p2][x]),DEBUG(M1[p1][x-1],M2[p2][x]);
if(M1[p1].count(x-1)&&M2[p3].count(x)) G[M1[p1][x-1]].push_back(M2[p3][x]),DEBUG(M1[p1][x-1],M2[p3][x]);
if(M2[p1].count(x+1)&&M1[p2].count(x)) G[M2[p1][x+1]].push_back(M1[p2][x]),DEBUG(M2[p1][x+1],M1[p2][x]);
if(M2[p1].count(x+1)&&M1[p3].count(x)) G[M2[p1][x+1]].push_back(M1[p3][x]),DEBUG(M2[p1][x+1],M1[p3][x]);
}
stack<int>S;
int SCC,dfn[5000005],low[5000005],Times,bel[5000005];
void Tarjan(int u)
{
S.push(u);
dfn[u]=low[u]=++Times;
for(int i=0;i<(int)G[u].size();i++)
{
int v=G[u][i];
if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
else if(!bel[v]) low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
int t=-1;SCC++;
while(t!=u)
{
t=S.top();S.pop();
bel[t]=SCC;
}
}
}
int main() {
// freopen("data26.in","r",stdin);
Ty1[1]='<'; Ty2[1]='>'; Ty2[2]='=';
int n,m;read(n);read(m);
for(int i=1,p1,p2,p3,x;i<=m;i++)
{
read(p1);read(p2);read(p3);read(x);
P[i]=node(p1,p2,p3,x);
brr[i]=x;
}
int tot=m;brr[++tot]=1;
sort(brr+1,brr+1+tot);
tot=unique(brr+1,brr+1+tot)-brr-1;
for(int i=1;i<=n;i++) M2[i][1]=++cnt,To[cnt]=mp(mp(i,1),2);
for(int i=1;i<=m;i++)
{
int p1=P[i].p1,p2=P[i].p2,p3=P[i].p3,x=P[i].x;
Init(p1,x); Init(p2,x); Init(p3,x);
Connect(p1,p2,p3,x); Connect(p2,p1,p3,x); Connect(p3,p1,p2,x);
}
for(int i=1;i<=n;i++)
{
auto it=M1[i].begin();
if(!M1[i].empty())
{
it++;
for(;it!=M1[i].end();it++) G[(*prev(it)).second].push_back((*it).second),DEBUG((*prev(it)).second,(*it).second);
}
it=M2[i].begin(); it++;
for(;it!=M2[i].end();it++) G[(*it).second].push_back((*prev(it)).second),DEBUG((*it).second,(*prev(it)).second);
}
for(int i=1;i<=cnt;i++) if(!dfn[i]) Tarjan(i);
for(int i=1;i<=n;i++)
{
for(auto it=M1[i].begin();it!=M1[i].end();it++)
{
int Val=(*it).first+1,id=(*it).second;
if(bel[id]==bel[M2[i][Val]]) return puts("NO")&0;
}
}
puts("YES");
for(int i=1;i<=n;i++)
{
for(auto it=M1[i].begin();it!=M1[i].end();it++)
{
int Val=(*it).first,x=(*it).second,y=M2[i][Val+1];
if(bel[x]<bel[y]) {printf("%d ",Val);break;}
}
if(!M1[i].size()) printf("1 ");
}
return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
6 4
1 3 4 2
1 2 5 6
3 6 6 7
2 4 5 3
4 2
1 2 3 2
2 3 4 3
*/
「GYM 1004160」Meet in the Middle
题意
\(~~~~\) 给定两棵均有 \(n-1\) 个点的带权树,\(q\) 次询问,一个人从第一棵树的 \(a\) 出发,另一个从第二棵树的 \(b\) 出发。求 \(\max_{i=1}^n dis_1(a,i)+dis_2(b,i)\)。
\(~~~~\) \(1\leq n\leq 10^5,1\leq q\leq 5\times 10^5\).
题解
\(~~~~\) 题目挺好的,部分分出得挺烂的,哦,不对,是根本没有。
\(~~~~\) 考虑如果所有询问的 \(b\) 固定,那我们有一种做法是在第一棵树的每个对应结点 \(i\) 再挂上一个点 \(i'\),中间边权为 \(dis_2(b,i)\)。那么现在的问题就是询问从 \(a\) 出发能到达的最远距离,显然维护直径的两个端点直接算距离就好了。
\(~~~~\) 那么当 \(b\) 不固定了的时候呢?我们把询问离线下来,那当 \(b\) 移动的时候会有一部分对应区间 (新移动到结点子树) 上挂的点直径下降,其他部分上升,那用一个线段树维护dfs序上一个区间的点集直径的端点即可。
代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
x*=f;
}
ll T,n,q;
struct ST{
vector <PII> G[100005];
ll f[20][400005],Siz[400005];
ll dep[400005],dis[400005],In[400005],Out[400005],To[400005],dfn[400005],Times;
void dfs1(ll u,ll fa)
{
dep[u]=dep[fa]+1; f[0][++Times]=u; To[u]=Times;
for(ll i=0;i<(ll)G[u].size();i++)
{
ll v=G[u][i].first;
if(v==fa) continue;
dis[v]=dis[u]+G[u][i].second;
dfs1(v,u);
f[0][++Times]=u;
}
}
void dfs2(ll u,ll fa)
{
dfn[u]=++Times; To[dfn[u]]=u; Siz[u]=1;
for(ll i=0;i<(ll)G[u].size();i++)
{
ll v=G[u][i].first,w=G[u][i].second;
if(v==fa) continue;
dis[v]=dis[u]+w; dfs2(v,u); Siz[u]+=Siz[v];
}
}
inline ll Min(ll a,ll b){return dep[a]<dep[b]?a:b;}
void Init()
{
for(ll i=1;i<=18;i++)
for(ll j=1;j+(1<<(i-1))<=Times;j++) f[i][j]=Min(f[i-1][j],f[i-1][j+(1<<(i-1))]);
}
inline ll LCA(ll x,ll y)
{
if(x==y) return x;
ll l=To[x],r=To[y];
if(l>r) swap(l,r);
ll d=__lg(r-l+1);
return Min(f[d][l],f[d][r-(1<<d)+1]);
}
ll Dis(ll x,ll y){return dis[x]+dis[y]-2*dis[LCA(x,y)];}
}ST1,ST2;
struct BIT{
ll tr[100005];
inline ll lowbit(ll x){return x&(-x);}
inline void Add(ll x,ll Val){for(;x<=n;x+=lowbit(x)) tr[x]+=Val;}
inline ll Query(ll x){ll ret=0;for(;x;x-=lowbit(x)) ret+=tr[x];return ret;}
inline void Modify(ll l,ll r,ll Val){if(l>r) return;Add(l,Val),Add(r+1,-Val);}
}BIT;
struct node{
ll u,v,w;
node(){u=v=w=0;}
node(ll U,ll V,ll W){u=U;v=V;w=W;}
};
struct SegmentTree{
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
node tr[400005];
ll Tag[400005];
node Merge(node a,node b)
{
ll c1=BIT.Query(ST2.dfn[a.u]),c2=BIT.Query(ST2.dfn[a.v]);
ll c3=BIT.Query(ST2.dfn[b.u]),c4=BIT.Query(ST2.dfn[b.v]);
ll u1=a.u,v1=a.v,w1=a.w;
ll u2=b.u,v2=b.v,w2=b.w;
ll u3=a.u,v3=b.v,w3=ST1.Dis(u3,v3)+c1+c4;
ll u4=a.u,v4=b.u,w4=ST1.Dis(u4,v4)+c1+c3;
ll u5=a.v,v5=b.u,w5=ST1.Dis(u5,v5)+c2+c3;
ll u6=a.v,v6=b.v,w6=ST1.Dis(u6,v6)+c2+c4;
ll Max=max(w1,max(w2,max(w3,max(w4,max(w5,w6)))));
if(Max==w1) return node(u1,v1,w1);
else if(Max==w2) return node(u2,v2,w2);
else if(Max==w3) return node(u3,v3,w3);
else if(Max==w4) return node(u4,v4,w4);
else if(Max==w5) return node(u5,v5,w5);
else return node(u6,v6,w6);
}
inline void pushUp(ll p){tr[p]=Merge(tr[ls],tr[rs]);}
void Build(ll p,ll l,ll r)
{
if(l==r)
{
tr[p]=node(ST2.To[l],ST2.To[l],ST2.dis[ST2.To[l]]*2);
return;
}
ll mid=(l+r)>>1;
Build(lson); Build(rson);
pushUp(p);
}
void pushTag(ll p,ll Val){tr[p].w+=2*Val; Tag[p]+=Val;}
void pushDown(ll p){if(Tag[p]) pushTag(ls,Tag[p]),pushTag(rs,Tag[p]),Tag[p]=0;}
void Modify(ll p,ll l,ll r,ll lx,ll rx,ll Val)
{
if(lx>rx) return;
if(lx<=l&&r<=rx) return pushTag(p,Val);
ll mid=(l+r)>>1; pushDown(p);
if(lx<=mid) Modify(lson,lx,rx,Val);
if(mid<rx) Modify(rson,lx,rx,Val);
pushUp(p);
}
#undef ls
#undef rs
#undef lson
#undef rson
}Seg;
ll Ans[500005];
vector <PII> Ask[100005];
void dfs3(ll u,ll fa)
{
ll U=Seg.tr[1].u,V=Seg.tr[1].v;
for(ll i=0;i<(ll)Ask[u].size();i++)
{
ll v=Ask[u][i].first,id=Ask[u][i].second;
Ans[id]=max(ST1.Dis(U,v)+BIT.Query(ST2.dfn[U]),ST1.Dis(V,v)+BIT.Query(ST2.dfn[V]));
}
for(ll i=0;i<(ll)ST2.G[u].size();i++)
{
ll v=ST2.G[u][i].first,w=ST2.G[u][i].second;
if(v==fa) continue;
ll l=ST2.dfn[v],r=ST2.dfn[v]+ST2.Siz[v]-1;
BIT.Modify(l,r,-w); BIT.Modify(1,l-1,w); BIT.Modify(r+1,n,w);
Seg.Modify(1,1,n,l,r,-w); Seg.Modify(1,1,n,1,l-1,w); Seg.Modify(1,1,n,r+1,n,w);
dfs3(v,u);
BIT.Modify(l,r,w); BIT.Modify(1,l-1,-w); BIT.Modify(r+1,n,-w);
Seg.Modify(1,1,n,l,r,w); Seg.Modify(1,1,n,1,l-1,-w); Seg.Modify(1,1,n,r+1,n,-w);
}
}
int main() {
read(T);
read(n);read(q);
for(ll i=1,u,v,w;i<n;i++)
{
read(u); read(v); read(w);
ST1.G[u].push_back(mp(v,w));
ST1.G[v].push_back(mp(u,w));
}
ST1.dfs1(1,0); ST1.Init();
for(ll i=1,u,v,w;i<n;i++)
{
read(u); read(v); read(w);
ST2.G[u].push_back(mp(v,w));
ST2.G[v].push_back(mp(u,w));
}
ST2.dfs2(1,0);
for(ll i=1;i<=n;i++) BIT.Modify(ST2.dfn[i],ST2.dfn[i],ST2.dis[i]);
Seg.Build(1,1,n);
for(ll i=1,a,b;i<=q;i++)
{
read(a);read(b);
Ask[b].push_back(mp(a,i));
}
dfs3(1,0);
for(ll i=1;i<=q;i++) printf("%lld\n",Ans[i]);
return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
*/
举办乘凉州喵,举办乘凉州谢谢喵
举办出题人,举办出题人谢谢喵。