syhc总结
令人期待的syhc终于开始了!!!
Day 1
我们首先迎来了铈哥的题目:
T1 Mush Dash(原创)
ljx正在玩一款叫Muse Dash的音乐节奏类游戏。
众所周知,ljx单身16年,所以手速特别快,每首曲子都能打出all perfect的最高评价。
然而这款游戏除了正常每个音符的固定得分外,还有一个fever机制。当你从游戏开始或上次fever状态结束后,击中每个音符都会为你的能量槽积攒能量,能量满后就可以进入fever状态,从而在接下来的
能量槽满时可以不立即进入fever状态,但由于能量槽已满,在此期间击中的音符不会为能量槽累积能量。
ljx想制霸该游排行榜,所以请你帮他计算一下他每首曲子可以在fever状态下击中几个音符。
---------------------------------------------------------------------------------------------
应该还是一道比较容易的DP吧,可是只有出题人铈哥自己以为是一道图论题(话说DP过程有点类似建图求最长路
T2 情报(CF1098C Construct a Tree)
ljx为得到全球各地妹子的情报,打算建立自己的情报组织。
ljx雇佣了
我们规定每个人的领导力 为该人所在的子树大小,ljx的支出为所有人的领导力之和。
ljx带了
同时,ljx抓来的人并不是很擅长情报工作,所以ljx希望每个人直接领导的人(即除父节点外且与该节点直接相连的点)的最大值
请你判断是否有符合条件的情报组织,如果有,请你输出
本题为多组测试。
---------------------------------------------------------------------------------------------
对于第一问,直接判断
对于第二问,很容易想到二分,然后用完全
此题难点在于第三问,但其实做出第二问之后第三问也不太难(可是窝考场上没敢写)。具体做法如下:在建树时,找出深度为某值的点有几个,然后微调树形。
在满
T3 大写锁定(CF1111E Tree)
9岁拧魔方破世界纪录的神童ldy的Caps Lock键忽然坏了。
经ldy的仔细检查,发现是电脑程序的内存分配出了问题。
该程序由
对于每个时刻,ldy的电脑会有一些关键程序以及一个核心程序
ldy早就想出了解决方案,但是他不知道有多少种解决方案,所以他把问题交给了你。
由于方案数可能很大,结果对
---------------------------------------------------------------------------------------------
我的做法是虚树,固定一个根节点建树。
ljx用
虚树做法:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define N 200020
typedef long long lint;
#define mod 1000000007
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
int n,m;
int q,k,r;
struct apple
{
int to,next;
}indexx[N];
int head[N],cnt;
void init(int x,int y)
{
indexx[++cnt].to=y;
indexx[cnt].next=head[x];
head[x]=cnt;
}
int dep[N],f[N][25],indegree[N],tot;
void dfs1(int u,int fa)
{
indegree[u]=++tot;
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<=20;i++)
{
f[u][i]=f[f[u][i-1]][i-1];
}
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
dfs1(v,u);
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y])
{
x=f[x][i];
}
}
if(x==y) return x;
for(int i=20;i>=0;i--)
{
if(dep[f[x][i]]&&f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
vector<int> tmp;
bool mp[N];
bool cmp(int x,int y)
{
return indegree[x]<indegree[y];
}
int st[N],tp;
struct orange
{
int to,next;
}iindex[N];
int ihead[N],icnt;
void iiit(int x,int y)
{
iindex[++icnt].to=y;
iindex[icnt].next=ihead[x];
ihead[x]=icnt;
}
void iinsert(int u)
{
if(u==1) return;
if(tp==1)
{
st[++tp]=u;
return;
}
int lc=lca(st[tp],u);
while(tp>1&&indegree[lc]<=indegree[st[tp-1]])
{
iiit(st[tp-1],st[tp]);
iiit(st[tp],st[tp-1]);
tp--;
}
if(st[tp]!=lc)
{
iiit(st[tp],lc);
iiit(lc,st[tp]);
st[tp]=lc;
}
st[++tp]=u;
return;
}
lint dp[303];
void dfs2(int u,int fa,int num)
{
if(mp[u])
{
for(int i=k;i>=0;i--)
{
if(i<=num) dp[i]=0;
else dp[i]=(dp[i-1]+(i-num)%mod*dp[i])%mod;
}
}
for(int i=ihead[u];i;i=iindex[i].next)
{
int v=iindex[i].to;
if(v!=fa)
{
dfs2(v,u,num+mp[u]);
}
}
ihead[u]=0;
mp[u]=0;
}
int main()
{
// freopen("capslock.in","r",stdin);
// freopen("capslock.out","w",stdout);
read(n),read(m);
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
init(x,y);
init(y,x);
}
dfs1(1,0);
while(m--)
{
read(q),read(k),read(r);
tmp.clear();
for(int i=1;i<=q;i++)
{
int x;
read(x);
mp[x]=1;
tmp.push_back(x);
}
if(!mp[r])
{
q++;
tmp.push_back(r);
}
sort(tmp.begin(),tmp.end(),cmp);
tp=0;
icnt=0;
st[++tp]=1;
for(int i=0;i<q;i++)
{
iinsert(tmp[i]);
}
while(tp)
{
if(tp-1)
{
iiit(st[tp],st[tp-1]);
iiit(st[tp-1],st[tp]);
}
tp--;
}
memset(dp,0,sizeof(dp));
dp[0]=1;
dfs2(r,0,0);
lint ans=0;
for(int i=0;i<=k;i++)
{
ans=(ans+dp[i])%mod;
}
printf("%lld\n",ans);
}
}
正解做法(出题人的代码):
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mod 1000000007
long long read()
{
long long x=0,f=1;char ch;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
struct edge
{
long long nxt,to;
}ed[205000];
long long head[105000],cnt;
long long n,q,a,b,c,d,dp[105000],rt_num[105000];
long long f[105000][21],dep[105000],used[105000];
long long que[205000],t,ta[205000],s[105000],e[105000];
bool cmp(long long a,long long b)
{
return rt_num[a]<rt_num[b];
}
void change(long long x,long long v)
{
if(x<=0)return ;
for(;x<=n*2;x+=(x&-x))ta[x]+=v;
}
long long query(long long x)
{
long long ans=0;
for(;x;x-=(x&-x))ans+=ta[x];
return ans;
}
void add(long long a,long long b)
{
ed[++cnt].to=b;ed[cnt].nxt=head[a];head[a]=cnt;
ed[++cnt].to=a;ed[cnt].nxt=head[b];head[b]=cnt;
}
void dfs(long long pos,long long fa)
{
if(used[pos])return ;
used[pos]++;
f[pos][0]=fa;dep[pos]=dep[fa]+1;
s[pos]=++t;
for(long long i=head[pos];i;i=ed[i].nxt)
{
dfs(ed[i].to,pos);
}
e[pos]=++t;
}
void lca_init()
{
for(long long i=1;i<=20;i++)
{
for(long long j=1;j<=n;j++)
f[j][i]=f[f[j][i-1]][i-1];
}
}
long long lca(long long a,long long b)
{
long long ans=0;
if(dep[a]<dep[b])swap(a,b);
for(long long i=20;i>=0;i--)
{
if(dep[f[a][i]]>=dep[b])a=f[a][i];
}
if(a==b)return a;
for(long long i=20;i>=0;i--)
{
if(f[a][i]==f[b][i])ans=f[a][i];
else a=f[a][i],b=f[b][i];
}
return ans;
}
int main()
{
// freopen("capslock.in","r",stdin);
// freopen("capslock.out","w",stdout);
n=read();q=read();
for(long long i=1;i<n;i++)
{
a=read();b=read();
add(a,b);
}
dfs(1,0);
lca_init();
for(long long i=1;i<=q;i++)
{
a=read();b=read();c=read();
for(long long j=1;j<=a;j++)
{
que[j]=read();
change(s[que[j]],1);
change(e[que[j]],-1);
}
for(long long j=1;j<=a;j++)
{
long long now=lca(que[j],c);
rt_num[que[j]]=query(s[que[j]])+query(s[c])-query(s[now])-query(s[f[now][0]])-1;//
}
sort(que+1,que+1+a,cmp);
dp[1]=1;
for(int j=2;j<=min(a,b);j++)dp[j]=0;
for(long long j=2;j<=a;j++)
{
for(long long k=min(a,b);k;k--)
{
dp[k]=(dp[k-1]+dp[k]*(k-rt_num[que[j]])%mod)%mod;
}
}
long long ans=0;
for(long long j=1;j<=min(a,b);j++)ans=(ans+dp[j])%mod;
printf("%lld\n",ans);
for(long long j=1;j<=a;j++)
{
change(s[que[j]],-1);
change(e[que[j]],1);
}
}
return 0;
}
(ljx巨佬
本场个人得分
我数据出锅了
全场人均得分这么低
还是看题目吧:
T1 摧毁敌人的秘密工厂(CF464E The Classic Problem)
绿元27年,
一开始没想到暴力进位会
修改过的标程如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef unsigned long long ulint;
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
#define N 100005
#define bas 233333
#define mod 1000000007
int n,m,cnt,head[N],dis[N],tot,lim,s,t;
lint punc1[N<<1],punc[N<<1];
bool vis[N];
struct apple
{
int to,next;
lint val;
}indexx[N*2];
struct Persistent_Segment_Tree
{
int lson,rson,val;
ulint has,has1;
}tree[N*240];
void init(int x,int y,lint w)
{
indexx[++cnt].to=y;
indexx[cnt].val=w;
indexx[cnt].next=head[x];
head[x]=cnt;
}
void push_up(int now)
{
tree[now].val=tree[tree[now].lson].val+tree[tree[now].rson].val;
tree[now].has=(tree[tree[now].lson].has+tree[tree[now].rson].has)%mod;
tree[now].has1=(tree[tree[now].lson].has1+tree[tree[now].rson].has1);
}
bool ssame(int x,int y)
{
int flag=1;
flag&=(tree[x].has==tree[y].has);
flag&=(tree[x].has1==tree[y].has1);
flag&=(tree[x].val==tree[y].val);
return flag;
}
bool comp(int x,int y,int l,int r)
{
if (l==r)
{
return tree[x].val>=tree[y].val;
}
int mid=(l+r)>>1;
if (!ssame(tree[x].rson,tree[y].rson)) return comp(tree[x].rson,tree[y].rson,mid+1,r);
else return comp(tree[x].lson,tree[y].lson,l,mid);
}
struct banana
{
int f,t;
banana(){}
banana(int f,int t):f(f),t(t){};
bool operator<(const banana &other)const
{
return comp(t,other.t,0,lim);
}
};
priority_queue<banana> q;
int build(int l,int r,int x)
{
int now=++tot;
if(l==r)
{
tree[now].val=x;
tree[now].has=punc[l]*x;
tree[now].has1=punc1[l]*x;
return now;
}
int mid=(l+r)>> 1;
tree[now].lson=build(l,mid,x);
tree[now].rson=build(mid+1,r,x);
push_up(now);
return now;
}
int query(int l,int r,int now,int st,int en)
{
if (st>r||en<l) return 0;
if (st<=l&&en>=r)
{
return tree[now].val;
}
int mid=(l+r)>>1;
return query(l,mid,tree[now].lson,st,en)+query(mid+1,r,tree[now].rson,st,en);
}
int find(int l,int r,int now,int p)
{
if(l==r) return l;
int mid=(l+r)>> 1;
if(p>mid) return find(mid+1,r,tree[now].rson,p);
if (query(l,mid,tree[now].lson,p,mid)==mid-p+1) return find(mid+1,r,tree[now].rson,mid+1);
else return find(l, mid, tree[now].lson,p);
}
int insert(int l,int r,int las,int p)
{
int now=++tot;
tree[now].lson=tree[las].lson,tree[now].rson=tree[las].rson;
if (l==r)
{
tree[now].val=1;
tree[now].has=punc[l];
tree[now].has1=punc1[l];
return now;
}
int mid=(l+r)>> 1;
if (p<=mid) tree[now].lson=insert(l,mid,tree[las].lson,p);
else tree[now].rson=insert(mid+1,r,tree[las].rson,p);
push_up(now);
return now;
}
int merge(int l,int r,int x,int y,int st,int en)
{
if (st>r||en<l) return x;
if (st<=l&&en>=r) return y;
int now=++tot;
int mid=(l+r)>>1;
tree[now].lson=merge(l,mid,tree[x].lson,tree[y].lson,st,en);
tree[now].rson= merge(mid+1,r,tree[x].rson,tree[y].rson,st,en);
push_up(now);
return now;
}
int add(int now, int x)
{
int p=find(0,lim,now,x);
int tmp=insert(0,lim,now,p);
if (p==x) return tmp;
tmp=merge(0,lim,tmp,dis[0],x,p-1);
return tmp;
}
void dijkstra()
{
int tmp=build(0, lim, 1);
for (int i=1;i<=n;i++)
{
dis[i]=tmp;
}
dis[0]=dis[s]=build(0,lim,0);
q.push(banana(s,dis[s]));
while(!q.empty())
{
while(!q.empty()&&vis[q.top().f])
{
q.pop();
}
banana temp=q.top();
int u=temp.f;
if(vis[u]) continue;
vis[u]=1;
for (int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
int tag=add(dis[u],indexx[i].val);
if(!comp(0,lim,dis[v],tag)) continue;
dis[v]=tag;
q.push(banana(v,dis[v]));
}
}
if(dis[t]==tmp)
{
puts("-1");
}
else
{
printf("%lld\n",tree[dis[t]].has%mod);
}
return;
}
int main()
{
// freopen("destroy.in","r",stdin);
// freopen("destroy.out","w",stdout);
read(n),read(m);
for (int i=1;i<=m;i++)
{
int x,y;
lint z;
read(x),read(y),read(z);
init(x,y,z);
init(y,x,z);
lim=max((lint)lim,z);
}
lim+=300;
punc[0]=1;
punc1[0]=1;
for (int i=1;i<=lim;i++)
{
punc[i]=punc[i-1]*2%mod;
punc1[i]=punc1[i-1]*bas;
}
read(s),read(t);
dijkstra();
return 0;
}
震惊
wh竟然用了
(是我太毒瘤了吗
T2 熊霸序列(AT3577 Largest Smallest Cyclic Shift)
绿元27年,在文化部长
途中,二人路过了居住着可爱的熊霸们的熊熊村,并用爱与希望解开了龟霸头部的怨念,救回了之前被抓走的村中的成年熊霸。
在
代码也就不到二十行吧......
对于能由其他队员占领的据点:
注意开
这大概是三道题里最水的一道了吧(
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
#define N 1000010
#define mod 998244353
int n,k;
int a[N];
struct apple
{
int to,next;
}indexx[N];
int head[N],cnt;
void init(int x,int y)
{
indexx[++cnt].to=y;
indexx[cnt].next=head[x];
head[x]=cnt;
}
bool flag;
int c[N];
int tmp[N];
int dp[N][2];
int punc[N];
vector<int> q;
void dfs(int u,int fa)
{
tmp[u]=a[u]>0;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v==fa) continue;
dfs(v,u);
if(!a[u]) a[u]=a[v];
else if(a[v]&&a[u]!=a[v])
{
flag=1;
}
tmp[u]+=tmp[v];
}
q.clear();
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
q.push_back(v);
}
}
punc[0]=1;
for(int i=0;i<(long long)q.size();i++)
{
int v=q[i];
punc[i+1]=(long long)punc[i]%mod*(dp[v][0]%mod+dp[v][1]%mod)%mod;
}
int siz=q.size();
if(!siz)
{
if(a[u])
{
dp[u][1]=1;
}
else
{
dp[u][0]=1;
dp[u][1]=0;
}
if(c[a[u]]==tmp[u]) a[u]=tmp[u]=0;
return;
}
if(a[u])
{
dp[u][1]=punc[siz];
}
else
{
dp[u][0]=punc[siz];
int tot=1;
for(int i=q.size()-1;i>=0;i--)
{
int v=q[i];
dp[u][1]=(dp[u][1]+(long long)tot*dp[v][1]%mod*punc[i]%mod)%mod;
tot=(long long)tot*(dp[v][0]+dp[v][1])%mod;
}
}
if(tmp[u]==c[a[u]]) tmp[u]=a[u]=0;
}
signed main()
{
// freopen("war.in","r",stdin);
// freopen("war.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
c[a[i]]++;
}
for(int i=1;i<n;i++)
{
int x,y;
scanf("%lld%lld",&x,&y);
init(x,y);
init(y,x);
}
dfs(1,0);
printf("%lld\n",flag?0:dp[1][1]);
}
Day 3
在第三天,出现了
T1 零件制造(CF1163F Indecisive Taxi Fee)
绿元27年,
很明显,制造如此巨大的航空母舰需要许多巨大的钢构件。如此巨大的构件只能在位于
---------------------------------------------------------------------------------------------
和我T1体量相当的数据结构维护图论题。
很明显,边权的改变分4种情况:
在
不在
在
不在
对于情况2,3,4而言,问题非常的简单:
现在考虑如何构造线段树,首先,对于一条连接了
以及:
那现在便只剩下一个问题了:如何计算
方法嘛,就是先跑一遍
#include<bits/stdc++.h>
using namespace std;
#define N 400040
typedef long long lint;
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
int n,m,p;
struct apple
{
int to,next;
lint val;
}indexx[N];
int head[N],cnt;
void init(int x,int y,lint w)
{
indexx[++cnt].to=y;
indexx[cnt].val=w;
indexx[cnt].next=head[x];
head[x]=cnt;
}
struct orange
{
int x,y;
lint z;
orange(){}
orange(int x,int y,lint z):x(x),y(y),z(z){};
}input[N];
lint dis[2][N],pre[2][N],from[2][N];
bool vis[2][N];
struct banana
{
int f;
lint t;
banana(){}
banana(int f,lint t):f(f),t(t){};
friend bool operator<(banana a,banana b)
{
return a.t>b.t;
}
};
priority_queue<banana> q;
void dijkstra(int s,int type)
{
for(int i=1;i<=n;i++)
{
dis[type][i]=1000000000000000ll;
}
memset(vis[type],0,sizeof(vis[type]));
while(!q.empty()) q.pop();
dis[type][s]=0;
q.push(banana(s,dis[type][s]));
while(!q.empty())
{
banana temp=q.top();
q.pop();
int u=temp.f;
if(vis[type][u]) continue;
vis[type][u]=1;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(dis[type][v]>dis[type][u]+indexx[i].val)
{
dis[type][v]=dis[type][u]+indexx[i].val;
pre[type][v]=(i+1)>>1;
from[type][v]=u;
q.push(banana(v,dis[type][v]));
}
}
}
}
bool used[N];
struct lemon
{
int x;
lint t;
}c;
lint ans;
bool type;
int top[2][N],dep[2][N];
void dfs(int u,int t)
{
top[type][u]=t;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(!top[type][v])
{
if(from[type][v]!=u) continue;
if(used[pre[type][v]])
{
dep[type][v]=dep[type][u]+1;
dfs(v,v);
}
else
{
dfs(v,t);
}
}
}
}
struct node
{
int l,r;
lint minn;
}tree[N*4];
void build(int l,int r,int now)
{
tree[now].l=l,tree[now].r=r;
tree[now].minn=100000000000000ll;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
build(l,mid,now*2);
build(mid+1,r,now*2+1);
}
void add(int l,int r,int now,lint x)
{
if(l>r) return;
if(l<=tree[now].l&&r>=tree[now].r)
{
tree[now].minn=min(tree[now].minn,x);
return;
}
int mid=(tree[now].l+tree[now].r)>>1;
if(l<=mid) add(l,r,now*2,x);
if(r>mid) add(l,r,now*2+1,x);
}
lint query(int l,int r,int now,int p)
{
if(l==r)
{
return tree[now].minn;
}
int mid=(tree[now].l+tree[now].r)>>1;
lint tmp=tree[now].minn;
if(p<=mid) tmp=min(tmp,query(l,mid,now*2,p));
else tmp=min(tmp,query(mid+1,r,now*2+1,p));
return tmp;
}
int main()
{
// freopen("parts.in","r",stdin);
// freopen("parts.out","w",stdout);
read(n),read(m),read(p);
for(int i=1;i<=m;i++)
{
read(input[i].x),read(input[i].y),read(input[i].z);
init(input[i].x,input[i].y,input[i].z);
init(input[i].y,input[i].x,input[i].z);
}
dijkstra(1,0);
dijkstra(n,1);
int now=n;
while(now)
{
used[pre[0][now]]=1;
now=from[0][now];
}
type=0;
dep[0][1]=1;
dfs(1,1);
type=1;
dep[1][n]=1;
dfs(n,n);
build(1,n,1);
for(int i=1;i<=m;i++)
{
if(!used[i])
{
int x=input[i].x,y=input[i].y;
int fx=top[0][x],fy=top[1][y];
add(dep[0][fx],dep[0][fy]-1,1,dis[0][x]+dis[1][y]+input[i].z);
fx=top[0][y],fy=top[1][x];
add(dep[0][fx],dep[0][fy]-1,1,dis[0][y]+dis[1][x]+input[i].z);
}
}
while(p--)
{
ans=dis[0][n];
read(c.x),read(c.t);
int x=input[c.x].x,y=input[c.x].y;
if(top[0][x]!=x||top[0][y]!=y||(from[0][x]!=y&&from[0][y]!=x))
{
if(c.t<input[c.x].z)
{
ans=min(ans,min(dis[0][x]+dis[1][y],dis[1][x]+dis[0][y])+c.t);
}
}
else
{
if(dep[0][x]>dep[0][y]) swap(x,y);
if(c.t<=input[pre[0][y]].z) ans+=(c.t-input[pre[0][y]].z);
else if(c.x==pre[0][y]) ans=min(ans+(c.t-input[pre[0][y]].z),query(1,n,1,dep[0][x]));
}
printf("%lld\n",ans);
}
}
打公式好累啊~
T2 反应堆组装(原创 题面有误,已删除)
---------------------------------------------------------------------------------------------
如果题面不错的话,大致就是一个弱化版的维修数列吧......
(什么
T3 母港选择(CF1182D Complete Mirror)
绿元31年,新的黑蛤蟆号下水了,如此巨大的军舰需要选择一个理想的母港,由于像
在选定母港之前
---------------------------------------------------------------------------------------------
很明显,如果我们选定的母港
所以母港存在时重心连接链的有两种可能:
Day 4
老大爷令人想要割jj的数学赛
T1 大保健(某咕P3986 斐波那契数列)
写出
T2 58号元素(CF1132G Greedy Subsequences)
使得:
现在 给(gēi)了你一个序列 ,她希望你找出一些子序列的最长贪心严格上升子序列的长度为多少。
可爱的
---------------------------------------------------------------------------------------------
题目比较套路吧......
首先用单调栈就可以轻松求出
考虑用线段树维护该树的
就是让你
#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
#define N 1000010
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
int n,k;
struct lemon
{
int x;
lint y;
bool operator<(const lemon &other)const
{
if(y==other.y)
{
return x<other.x;
}
return y<other.y;
}
}input[N];
int high[N],tot;
int st[N],top;
int f[N];
struct apple
{
int to,next;
}indexx[N];
int head[N],cnt;
void init(int x,int y)
{
indexx[++cnt].to=y;
indexx[cnt].next=head[x];
head[x]=cnt;
}
int l[N],idcnt,siz[N];
stack<int> tmp;
void bfs()
{
tmp.push(n);
while(!tmp.empty())
{
int u=tmp.top();
tmp.pop();
l[u]=++idcnt;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
tmp.push(v);
}
}
}
struct node
{
int l,r;
int val,maxn;
}tree[4*N];
void push_up(int now)
{
tree[now].maxn=max(tree[now*2].maxn,tree[now*2+1].maxn)+tree[now].val;
}
void build(int l,int r,int now)
{
tree[now].l=l,tree[now].r=r;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
build(l,mid,now*2);
build(mid+1,r,now*2+1);
}
void add(int l,int r,int now,int x)
{
if(l<=tree[now].l&&r>=tree[now].r)
{
tree[now].val+=x;
tree[now].maxn+=x;
return;
}
int mid=(tree[now].l+tree[now].r)>>1;
if(l<=mid) add(l,r,now*2,x);
if(r>mid) add(l,r,now*2+1,x);
push_up(now);
return;
}
int main()
{
// freopen("lizard.in","r",stdin);
// freopen("lizard.out","w",stdout);
read(n),read(k);
for(int i=1;i<=n;i++)
{
read(input[i].y);
input[i].x=i;
siz[i]=1;
}
siz[n+1]=1;
sort(input+1,input+n+1);
for(int i=1;i<=n;i++)
{
if(input[i].y!=input[i-1].y) ++tot;
high[input[i].x]=tot;
}
for(int i=1;i<=n;i++)
{
while(top&&high[st[top]]<high[i]) siz[i]+=siz[st[top]],f[st[top--]]=i;
st[++top]=i;
}
while(top) siz[n+1]+=siz[st[top]],f[st[top--]]=n+1;
for(int i=1;i<=n;i++)
{
init(f[i],i);
}
n++;
bfs();
build(1,n,1);
for(int i=1;i<n;i++)
{
add(l[i],l[i]+siz[i]-1,1,1);
if(i>k)add(l[i-k],l[i-k]+siz[i-k]-1,1,-1);
if(i>=k) printf("%d ",tree[1].maxn);
}
}
T3 整数(
求下式的值:
(\lfloor \sqrt{9t^2+4t+\frac{1}{4}}+3t+\frac{1}{2})^n \rfloor mod7528443412579576937
---------------------------------------------------------------------------------------------
就连大爷自己一开始也没想到的神仙题目......
首先,令
再令
接下来写出
显然(
然后我们发现:
神奇思路:
构造方程:
得到数列:
#include<bits/stdc++.h>
using namespace std;
#define mod 7528443412579576937ll
typedef unsigned long long lint;
int m;
lint t,n;
struct matrix
{
lint num[2][2];
};
lint add(lint a,lint b)
{
return (a+b>mod)?a+b-mod:a+b;
}
lint multiply(lint a,lint b)
{
lint sum=0,f=1;
if(a<0) a=-a,f=-f;
if(b<0) b=-b,f=-f;
while(b)
{
if(b&1)
{
sum=add(sum,a);
b--;
}
a=add(a,a);
b>>=1;
}
return sum*f%mod;
}
matrix A;
matrix multiply(matrix a,matrix b)
{
matrix c;
memset(&c,0,sizeof(c));
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
{
for(int k=0;k<=1;k++)
{
c.num[i][j]=add(c.num[i][j],multiply(a.num[i][k],b.num[k][j]));
}
}
}
return c;
}
matrix E=
{
1,0,
0,1
};
matrix ksm(matrix a,lint b)
{
matrix product=E;
while(b)
{
if(b&1)
{
product=multiply(product,a);
b--;
}
a=multiply(a,a);
b>>=1;
}
return product;
}
int main()
{
// freopen("int.in","r",stdin);
// freopen("int.out","w",stdout);
scanf("%d",&m);
while(m--)
{
scanf("%llu%llu",&t,&n);
if(!n||!t)
{
printf("1\n");
continue;
}
A.num[0][0]=(6*t+1)%mod;
A.num[1][0]=t;
A.num[0][1]=1;
A.num[1][1]=0;
matrix B=ksm(A,n-1);
printf("%llu\n",add(multiply(B.num[0][0],(6*t+1)),multiply(B.num[1][0],2))+(n&1?0:-1));
}
}
本场个人得分
Day 5
周老师:今天考谁的题
答:ljx的吧......
周老师:好,就考ljx的题
T1 在水下我们是无敌的(
众所周知,九条理希是一个有着强大力量的魔女,现正在
绿元27年,在
混战之中,敌军旗舰“杆孒徳”号不慎独自脱离了战场。亲临战场指挥的
但意想不到的是,“杆孒徳”号作为超重战列舰却有着远超轻型驱逐舰的
由于理希记性不好,她对需要背一大堆奇怪咒语的魔法一窍不通,而不巧的是这种冻结魔法就是这样的。
经过理希研究,这种古老的只由小写字母组成的不明所以的冻结魔法的咒语看似冗长,实际只有
具体规则:
对于吟唱的一个字符串
理希背不下来关键词,于是放空大脑,吟唱各种奇怪的字符串,反正最后是成功困住并击沉了“杆孒徳”号。
理希对魔法的效果感到十分惊讶,于是在战后决定再次测试瞎吟唱来发动魔法的效果,这次她请到了你来帮忙记录。
现在你已经知道了这
第一种:
第二种:
---------------------------------------------------------------------------------------------
看到子串考虑建出
这个做法好像叫什么“树链的并”。
简而言之:
所有走到的点按
查询时直接查询对应点所在子树也就是
然而窝铈在了玄学类型转换上......
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define N 2000020
#define M 100010
#define lint long long
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
int n;
char s[N];
int pos[M],lx[M];
struct Trie
{
int to[26],fail;
}tree[N];
int root=1,tot=1;
void insert(char *c,int id)
{
int len=strlen(c),now=root;
for(int i=0;i<len;i++)
{
int cc=c[i]-'a';
if(!tree[now].to[cc]) tree[now].to[cc]=++tot;
now=tree[now].to[cc];
}
pos[id]=now;
lx[id]=len;
}
queue<int> q;
void get_fail()
{
for(int i=0;i<26;i++)
{
tree[0].to[i]=1;
}
q.push(root);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<26;i++)
{
int &v=tree[u].to[i];
if(v)
{
tree[v].fail=tree[tree[u].fail].to[i];
q.push(v);
}
else
{
v=tree[tree[u].fail].to[i];
}
}
}
}
struct apple
{
int to,next;
}indexx[N];
int head[N],cnt;
void init(int x,int y)
{
indexx[++cnt].to=y;
indexx[cnt].next=head[x];
head[x]=cnt;
}
int dep[N],f[N],top[N],siz[N],max_son[N],l[N],r[N],dfn_id;
void dfs1(int u,int fa)
{
f[u]=fa;
dep[u]=dep[fa]+1;
siz[u]=1;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[max_son[u]])
{
max_son[u]=v;
}
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
l[u]=++dfn_id;
if(!max_son[u])
{
r[u]=dfn_id;
return;
}
dfs2(max_son[u],t);
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=f[u]&&v!=max_son[u])
{
dfs2(v,v);
}
}
r[u]=dfn_id;
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
int m;
bool cmp(int a,int b)
{
return l[a]<l[b];
}
lint c1[N],c2[N];
int lowbit(int x)
{
return x&(-x);
}
void add(lint *c,int p,int x)
{
while(p<=2000000)
{
c[p]+=x;
p+=lowbit(p);
}
}
lint query(lint *c,int p)
{
lint ans=0;
while(p)
{
ans+=c[p];
p-=lowbit(p);
}
return ans;
}
vector<int> val;
int main()
{
// freopen("invincibility.in","r",stdin);
// freopen("invincibility.out","w",stdout);
read(n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
insert(s,i);
}
get_fail();
for(int i=2;i<=tot;i++)
{
init(tree[i].fail,i);
}
dfs1(1,0);
dfs2(1,1);
read(m);
while(m--)
{
int op;
read(op);
switch(op)
{
case 1:
{
scanf("%s",s);
int len=strlen(s),now=root;
val.clear();
for(int i=0;i<len;i++)
{
now=tree[now].to[s[i]-'a'];
val.push_back(now);
}
sort(val.begin(),val.end(),cmp);
for(int i=0;i<val.size();i++)
{
add(c1,l[val[i]],1);
add(c2,l[val[i]],len);
}
for(int i=0;i<val.size()-1;i++)
{
add(c1,l[lca(val[i],val[i+1])],-1);
add(c2,l[lca(val[i],val[i+1])],-len);
}
break;
}
case 2:
{
int x;
read(x);
lint tmp1=(query(c1,r[pos[x]])-query(c1,l[pos[x]]-1))*lx[x];
lint tmp2=(query(c2,r[pos[x]])-query(c2,l[pos[x]]-1));
printf("%lld\n",tmp2-tmp1);
break;
}
}
}
return 0;
}
T2 牛油果(CF986F Oppa Funcan Style Remastered)
题目背景取自ljx自己被飞来的牛油果砸到的经历......(如果点赞的话,没准我还会告诉你事情的真相......)
众所周知,九条理希是一个可爱的小萝莉。
众所周知,在上一题中她刚刚击沉了“杆孒徳”号战列舰,战斗结束后准备买菜回家。
在这时,从远处突然飞来好几批的牛油果,径直向理希飞来。
理希并没有马上躲避,因为她注意到这些牛油果每一批的数量都是同一个数的约数而且都不为
于是她想知道一共有多少牛油果飞了过来。但在这之前一个大牛油果径直打在了理希的头上给她砸晕了。理希醒来之后除了牛油果个数的特点以外什么也记不起来了,所以她按照仅有的记忆猜测有多少牛油果以及那个数是多少。
也就是说,她会询问
---------------------------------------------------------------------------------------------
我们发现只用
不知道
反正我写的
#include<bits/stdc++.h>
using namespace std;
#define N 200020
typedef long long lint;
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
ret=(TP)x*f;
}
int t;
struct node
{
lint n,k;
int id;
bool operator<(const node &other)const
{
return k<other.k;
}
}a[10010];
lint bas[5]={2,3,7,61,24251};
lint gcd(lint x,lint y)
{
if(!y)
{
return x;
}
return gcd(y,x%y);
}
lint add(lint a,lint b,lint mod)
{
return (a+b>mod)?a+b-mod:a+b;
}
lint ksc(lint a,lint b,lint mod)
{
lint sum=0;
while(b)
{
if(b&1)
{
sum=add(sum,a,mod);
b--;
}
a=add(a,a,mod);
b>>=1;
}
return sum%mod;
}
lint ksm(lint a,lint b,lint mod)
{
lint product=1;
while(b)
{
if(b&1)
{
product=ksc(product,a,mod);
b--;
}
a=ksc(a,a,mod);
b>>=1;
}
return product%mod;
}
bool Miller_Rabin(lint x,lint b)
{
if(ksm(b,x-1,x)!=1) return 0;
lint k=x-1;
while(!(k&1))
{
k>>=1;
lint d=ksm(b,k,x);
if(d!=1&&d!=x-1) return 0;
if(d==x-1) return 1;
}
return 1;
}
bool Miller_Rabin(lint x)
{
if(x<2||x==46856248255981) return 0;
for(int i=0;i<5;i++)
{
if(x==bas[i]) return 1;
}
for(int i=0;i<5;i++)
{
if(!Miller_Rabin(x,bas[i])) return 0;
}
return 1;
}
lint Mandelbrot(lint x,lint c,lint p)
{
return (ksc(x,x,p)+c)%p;
}
lint Pollard_Rho(lint x)
{
lint s,t,c=1ll*rand()%(x-1)+1;
s=t=0;
lint val=1;
int goal=1;
for(;;goal<<=1,s=t,val=1)
{
for(int i=1;i<=goal;i++)
{
t=Mandelbrot(t,c,x);
val=ksc(val,abs(t-s),x);
if(!(i%127))
{
lint g=gcd(val,x);
if(g>1) return g;
}
}
lint g=gcd(val,x);
if(g>1) return g;
}
}
vector<lint> fac;
lint min_factor;
void divide(lint x)
{
if(x<2)
{
return;
}
if(Miller_Rabin(x))
{
min_factor=min(min_factor,x);
fac.push_back(x);
return;
}
lint p=x;
while(p>=x) p=Pollard_Rho(x);
while(!(x%p))
{
x/=p;
}
divide(x);
divide(p);
}
lint exgcd(lint a,lint b,lint &x,lint &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
lint d=exgcd(b,a%b,x,y);
lint res=x;
x=y;
y=res-a/b*y;
return d;
}
lint dis[N];
bool vis[N];
queue<int> q;
void spfa(lint mod)
{
for(int i=0;i<mod;i++)
{
dis[i]=1000000000000000000ll;
vis[i]=0;
}
dis[0]=0;
q.push(0);
vis[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=1;i<fac.size();i++)
{
int v=(u+fac[i])%mod;
if(dis[v]>dis[u]+fac[i])
{
dis[v]=dis[u]+fac[i];
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
}
bool ans[10010];
int main()
{
// freopen("bpk.in","r",stdin);
// freopen("bpk.out","w",stdout);
srand(time(NULL));
read(t);
for(int i=1;i<=t;i++)
{
read(a[i].n),read(a[i].k);
a[i].id=i;
}
sort(a+1,a+t+1);
for(int i=1;i<=t;i++)
{
int now=i;
while(now<t&&a[now+1].k==a[i].k) now++;
if(a[i].k==1)
{
i=now;
continue;
}
fac.clear();
min_factor=1000000000000000000ll;
divide(a[i].k);
sort(fac.begin(),fac.end());
if(fac.size()==1)
{
for(int j=i;j<=now;j++)
{
if(!(a[j].n%fac[0])) ans[a[j].id]=1;
}
i=now;
continue;
}
if(fac.size()==2)
{
lint x,y;
lint g=exgcd(fac[0],fac[1],x,y);
lint b=fac[1]/g;
x=add(x,b,b);
for(int j=i;j<=now;j++)
{
if(!(a[j].n%g))
{
lint dx=x,dy=y;
dx=ksc(dx,a[j].n/g,b);
dy=(a[j].n-fac[0]*dx)/fac[1];
if(dy>=0) ans[a[j].id]=1;
}
}
i=now;
continue;
}
spfa(min_factor);
for(int j=i;j<=now;j++)
{
if(dis[a[j].n%min_factor]<=a[j].n) ans[a[j].id]=1;
}
i=now;
}
for(int i=1;i<=t;i++)
{
printf("%s\n",ans[i]?"YES":"NO");
}
return (0^0);
}
T3 孕育禁果的蔷薇(CF1140G Double Tree)
众所周知,九条理希是一个强大的魔女。
众所周知就在上一题理希被牛油果砸晕了,在这之后,她灵机一动创作了一个的可以扔水果攻击的魔法,命名为
由于是由理希的魔力凝结而成,这棵树有着奇特的力量,它上面的每个节点都一分为二。
说白了这棵树有
这棵树有三组边:
第一组:对于每个
第二组:对于所有奇数点,共有
第三组:对于每一条第二组中的边
问题很简单了:因为理希要尽量减少魔力流动的损耗以便尽可能多地用这个魔法蹂躏
---------------------------------------------------------------------------------------------
首先将这个咋看都是图的玩意重新变为每个点有两个状态的树。
可以先通过树上DP求出每个点转换状态的最小花费。
在这之后我们要考虑一下如何求出任意两点到LCA的花费。
设
之后对于一对点的询问的答案将在求LCA过程中得出。
ljx本人口口声声说只有离线
倍增版:
#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
#define N 600060
template<typename TP> inline void read(TP &ret)
{
TP x=0,f=1;
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();}
ret=(TP)x*f;
}
int n;
lint a[N];
int lg2[N];
struct apple
{
int to,next;
lint val1,val2;
}indexx[N];
int head[N],cnt;
void init(int x,int y,lint z,lint w)
{
indexx[++cnt].to=y;
indexx[cnt].val1=z;
indexx[cnt].val2=w;
indexx[cnt].next=head[x];
head[x]=cnt;
}
lint dp[N][20][2][2];
int f[N][20];
int dep[N];
void switch01(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
switch01(v,u);
a[u]=min(a[u],indexx[i].val1+a[v]+indexx[i].val2);
}
}
}
void switch10(int u,int fa)
{
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
a[v]=min(a[v],indexx[i].val1+a[u]+indexx[i].val2);
switch10(v,u);
}
}
}
void dfs1(int u,int fa)
{
for(int i=head[u];i;i=indexx[i].next)
{
int v=indexx[i].to;
if(v!=fa)
{
dp[v][0][0][0]=min(indexx[i].val1,indexx[i].val2+a[u]+a[v]);
dp[v][0][0][1]=min(a[v]+indexx[i].val2,a[u]+indexx[i].val1);
dp[v][0][1][0]=min(a[v]+indexx[i].val1,a[u]+indexx[i].val2);
dp[v][0][1][1]=min(indexx[i].val2,indexx[i].val1+a[u]+a[v]);
dfs1(v,u);
}
}
}
void up()
{
for(int j=1;j<=lg2[n];j++)
{
for(int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
dp[i][j][0][0]=min(dp[i][j-1][0][0]+dp[f[i][j-1]][j-1][0][0],dp[i][j-1][0][1]+dp[f[i][j-1]][j-1][1][0]);
dp[i][j][0][1]=min(dp[i][j-1][0][0]+dp[f[i][j-1]][j-1][0][1],dp[i][j-1][0][1]+dp[f[i][j-1]][j-1][1][1]);
dp[i][j][1][0]=min(dp[i][j-1][1][0]+dp[f[i][j-1]][j-1][0][0],dp[i][j-1][1][1]+dp[f[i][j-1]][j-1][1][0]);
dp[i][j][1][1]=min(dp[i][j-1][1][1]+dp[f[i][j-1]][j-1][1][1],dp[i][j-1][1][0]+dp[f[i][j-1]][j-1][0][1]);
}
}
}
int m;
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=lg2[n];i>=0;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=lg2[n];i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
lint f1[N],f2[N];
lint solve(int x,int y)
{
int u=(x+1)>>1,v=(y+1)>>1;
if(dep[u]<dep[v])
{
swap(u,v);
swap(x,y);
}
int lc=lca(u,v);
f1[(x+1)&1]=0;
f1[((x+1)&1)^1]=a[u];
for(int i=lg2[n];i>=0;i--)
{
if(dep[f[u][i]]>=dep[lc])
{
lint w0=f1[0],w1=f1[1];
f1[0]=min(w0+dp[u][i][0][0],w1+dp[u][i][1][0]);
f1[1]=min(w0+dp[u][i][0][1],w1+dp[u][i][1][1]);
u=f[u][i];
}
}
u=v;
f2[(y+1)&1]=0;
f2[((y+1)&1)^1]=a[u];
for(int i=lg2[n];i>=0;i--)
{
if(dep[f[u][i]]>=dep[lc])
{
lint w0=f2[0],w1=f2[1];
f2[0]=min(w0+dp[u][i][0][0],w1+dp[u][i][1][0]);
f2[1]=min(w0+dp[u][i][0][1],w1+dp[u][i][1][1]);
u=f[u][i];
}
}
return min(f1[0]+f2[0],f1[1]+f2[1]);
}
int main()
{
// freopen("rose.in","r",stdin);
// freopen("rose.out","w",stdout);
read(n);
lg2[1]=0;
for(int i=2;i<=n;i++)
{
lg2[i]=lg2[i>>1]+1;
}
for(int i=1;i<=n;i++)
{
read(a[i]);
}
for(int i=1;i<n;i++)
{
int x,y;
lint z,w;
read(x),read(y),read(z),read(w);
init(x,y,z,w);
init(y,x,z,w);
}
memset(&dp,127/2,sizeof(dp));
switch01(1,0);
switch10(1,0);
dfs1(1,0);
up();
read(m);
while(m--)
{
int x,y;
read(x),read(y);
printf("%lld\n",solve(x,y));
}
}
离线
#include<cstdio>
#include<algorithm>
#include<cstring>
using std::min;
typedef long long lint;
const int N=300069,M=600069;
template<typename TP>
inline void read(TP &_t)
{
TP _r=0,_f=1;char _c=getchar();
while(_c<'0'||_c>'9'){if(_c=='-')_f=-1;_c=getchar();}
while(_c>='0'&&_c<='9'){_r=_r*10+_c-'0';_c=getchar();}
_t=_r*_f;
}
struct sumireko{int to,ne;lint w1,w2;}e[M];
int he[N],ecnt;
void addline(int f,int t,lint w1,lint w2)
{
e[++ecnt].to=t;
e[ecnt].ne=he[f];
e[ecnt].w1=w1,e[ecnt].w2=w2;
he[f]=ecnt;
}
int n;
lint scost[N];
void gsc1(int x,int f)
{
for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
if(t!=f) gsc1(t,x),scost[x]=min(scost[x],scost[t]+e[i].w1+e[i].w2);
}
void gsc2(int x,int f)
{
for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
if(t!=f) scost[t]=min(scost[t],scost[x]+e[i].w1+e[i].w2),gsc2(t,x);
}
/*
*0->00
*1->01
*2->10
*3->11
*/
lint dp[N][4];
void gdp(int x,int f)
{
for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
if(t!=f)
dp[t][0]=min(e[i].w1,e[i].w2+scost[x]+scost[t]),
dp[t][1]=min(e[i].w2+scost[t],e[i].w1+scost[x]),
dp[t][2]=min(scost[x]+e[i].w2,e[i].w1+scost[t]),
dp[t][3]=min(e[i].w2,e[i].w1+scost[x]+scost[t]),
gdp(t,x);
}
void get_switch_cost(){gsc1(1,0),gsc2(1,0),gdp(1,0);}
int fa[N];
int T;
void find(int x)
{
if(fa[x]!=fa[fa[x]])
{
find(fa[x]);
int f=fa[x];
dp[0][0]=dp[0][1]=dp[0][2]=dp[0][3]=0;
dp[0][0]=min(dp[x][0]+dp[f][0],dp[x][1]+dp[f][2]);
dp[0][1]=min(dp[x][0]+dp[f][1],dp[x][1]+dp[f][3]);
dp[0][2]=min(dp[x][2]+dp[f][0],dp[x][3]+dp[f][2]);
dp[0][3]=min(dp[x][3]+dp[f][3],dp[x][2]+dp[f][1]);
memcpy(dp[x],dp[0],sizeof(dp[x]));
fa[x]=fa[fa[x]];
}
}
struct ques{int ne,id;}q[M<<1];
int qh[N],qcnt;
void addques(int f,int id)
{
q[++qcnt].id=id;
q[qcnt].ne=qh[f];
qh[f]=qcnt;
}
int qt[M<<1][2],qs[M<<1];
struct gat{int id,ne;}g[M<<1];
int gh[N],gcnt;
void addgat(int f,int id)
{
g[++gcnt].id=id;
g[gcnt].ne=gh[f];
gh[f]=gcnt;
}
bool vv[N];
lint ans[M];
void dfs(int x,int f)
{
vv[x]=1;
for(int i=qh[x],t;i;i=q[i].ne)
{
t=qt[q[i].id][1];
if(vv[t]) find(t),addgat(fa[t],q[i].id);
}
for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
if(t!=f) dfs(t,x),fa[t]=x;
for(int i=gh[x],id;i;i=g[i].ne)
{
id=g[i].id;
if(qt[id][1]!=x)
{
int xi=qt[id][0],yi=qt[id][1];
int xp=qs[id]>>1,yp=qs[id]&1;
find(xi),find(yi);
ans[id>T?id-T:id]=min(dp[xi][xp<<1]+dp[yi][yp<<1],dp[xi][(xp<<1)|1]+dp[yi][(yp<<1)|1]);
}
else find(qt[id][0]),ans[id>T?id-T:id]=dp[qt[id][0]][qs[id]];
}
}
int xi,yi,xp,yp;
lint wi1,wi2;
signed main()
{
// freopen("rose.in","r",stdin);
// freopen("rose.out","w",stdout);
read(n);
for(int i=1;i<=n;i++) read(scost[i]),fa[i]=i;
for(int i=1;i<n;i++) read(xi),read(yi),read(wi1),read(wi2),addline(xi,yi,wi1,wi2),addline(yi,xi,wi1,wi2);
get_switch_cost();
read(T);
for(int i=1;i<=T;i++)
{
read(xi),read(yi);
xp=(xi&1)^1,xi=xi+1>>1;
yp=(yi&1)^1,yi=yi+1>>1;
qt[i][0]=qt[i+T][1]=xi;
qt[i][1]=qt[i+T][0]=yi;
qs[i]=(xp<<1)|yp,qs[i+T]=(yp<<1)|xp;
if(xi==yi){ans[i]=xp==yp?0:scost[xi];continue;}
addques(xi,i),addques(yi,i+T);
}
dfs(1,0);
for(int i=1;i<=T;i++) printf("%I64d\n",ans[i]);
return 0;
}
本场得分
持续更新中......