多校A层冲刺NOIP2024模拟赛07
多校A层冲刺NOIP2024模拟赛07
\(T1\) A. 限速(speed) \(40pts\)
-
设最终保留的边的权值构成的集合为 \(S\) 。那么其贡献为 \(\begin{cases} k-\max\limits_{x \in S}\{ x \} & \max\limits_{x \in S}\{ x \} \le k \\ \sum\limits_{x \in S}[x>k] \times (x-k) & \max\limits_{x \in S}\{ x \}>k \end{cases}\) 。
-
两种情况一起考虑贡献不太好做,考虑分开统计。
-
若仅用边权 \(\le k\) 的边无法使整张图连通,则类似 \(Kruskal\) 的写法逐个将边权 \(>k\) 的边加入其中,直接统计贡献。
-
若仅用边权 \(\le k\) 的边可以使整张图连通,又分为两种情况。
- 若仅用边权 \(\le k\) 的边,则直接统计贡献。
- 否则可以证明最多加入一条边权 \(>k\) 的边(且任意一条边均可以)替换一条边权 \(\le k\) 的边从而使得图连通,得到的贡献和上个贡献取 \(\min\) 。
点击查看代码
struct node { ll from,to,w; }e[200010]; bool cmp(node a,node b) { return a.w<b.w; } struct DSU { ll fa[200010]; void init(ll n) { for(ll i=1;i<=n;i++) { fa[i]=i; } } ll find(ll x) { return (fa[x]==x)?x:fa[x]=find(fa[x]); } }D; int main() { freopen("speed.in","r",stdin); freopen("speed.out","w",stdout); ll n,m,k,len,maxx=0,sum=0,cnt=0,ans=0,x,y,i; cin>>n>>m>>k; len=m; for(i=1;i<=m;i++) { cin>>e[i].from>>e[i].to>>e[i].w; } sort(e+1,e+1+m,cmp); for(i=1;i<=m;i++) { if(e[i].w>k) { len=i-1; break; } } D.init(n); for(i=len;i>=1;i--) { x=D.find(e[i].from); y=D.find(e[i].to); if(x!=y) { D.fa[x]=y; cnt++; maxx=max(maxx,e[i].w); } } if(cnt==n-1) { ans=k-maxx; if(len+1<=m) { ans=min(ans,e[len+1].w-k); } } else { for(i=len+1;i<=m;i++) { x=D.find(e[i].from); y=D.find(e[i].to); if(x!=y) { D.fa[x]=y; sum+=e[i].w-k; } } ans=sum; } cout<<ans<<endl; fclose(stdin); fclose(stdout); return 0; }
\(T2\) B. 酒鬼 (drunkard) \(18pts\)
-
部分分
- 子任务 \(1\) :先走到 \(q_{i}\) ,然后开始左右移动从而拖延时间,故 \((q_{i}-(p_{i}-1)) \mod 2\) 即为所求。
- 子任务 \(2\) :直接走到 \(q_{i}\) ,故 \(q_{i}-(p_{i}-1)\) 即为所求。
点击查看代码
string s; int main() { freopen("drunkard.in","r",stdin); freopen("drunkard.out","w",stdout); int n,m,p,q,i; cin>>n>>m; if(m==2) { cin>>s>>p>>q; cin>>s; if(s=="min") { if((q-(p-1))%2==0) { cout<<0<<endl; } else { cout<<1<<endl; } } else { cout<<q-(p-1)<<endl; } } else { for(i=1;i<=m;i++) { cin>>s; if(s=="clue") { cin>>p>>q; } else { cout<<"bad"<<endl; } } } fclose(stdin); fclose(stdout); return 0; }
-
正解
- 考虑将操作按照时间维 \(q\) 升序排序。
- 一些乱七八糟的性质
- 发现当 \(t_{0}\) 确定时,每个时刻所在的位置的奇偶性是固定的。
- 最大值为 \(\infty\) 当且仅当没有操作或 \(\forall i,p_{i}=1\) ,否则一定等于 \(\min\limits_{p_{i} \ge2}\{ q_{i}-(p_{i}-1) \}\) 。
- 因为在之前的操作中已经判断了是否有解,故可以直接钦定前后合法,通过时间差和位移差来判断是否合法。
- 若 \(\forall i,p_{i} \le 2\) 则最小值答案只会是 \(0\) 或 \(1\) ;\(\exists i,p_{i}=1\) 的情况比较难处理,因为要判断是先走然后再走回来还是一直睡觉在恰当时间开始走,而且不保证奇偶性合法。
-
考虑特殊处理 \(p_{i}=1\) 的情况。
- 保留最早的一个 \(p_{i} \ge 2\) 的时间 \(tim\) 。
- 当奇偶性不同时更新在符合当前约束下的最晚移动时间 \(last\) ;及时清楚不符合当前约束的 \(last\) 。
- 若 \(last>tim\) 则不合法。
- 询问 \(\min\) 时和上一个时间的出发时间取 \(\min\) 即可。
点击查看代码
set<pair<int,int> >s; set<pair<int,int> >::iterator it,pre,nxt; int main() { freopen("drunkard.in","r",stdin); freopen("drunkard.out","w",stdout); int n,m,p,q,maxx=0x7f7f7f7f,tim=0x7f7f7f7f,flag=0,last=-1,i; string pd; cin>>n>>m; for(i=1;i<=m;i++) { cin>>pd; if(flag==1) { if(pd=="clue") { cin>>p>>q; } else { cout<<"bad"<<endl; } } else { if(pd=="clue") { cin>>p>>q; if(p-1>q) { flag=1; } else { if(p>=2) { tim=min(tim,q); maxx=min(maxx,q-(p-1)); } it=s.insert(make_pair(q,p)).first; nxt=next(it); if(it!=s.begin()) { pre=prev(it); flag|=(abs(pre->second-p)>q-pre->first); last=(nxt!=s.end()&&nxt->first==last)?-1:last; if((pre->first-(pre->second-1))%2!=(q-(p-1))%2) { last=max(last,q); } } if(nxt!=s.end()) { flag|=(abs(nxt->second-p)>nxt->first-q); if((nxt->first-(nxt->second-1))%2!=(q-(p-1))%2) { last=max(last,nxt->first); } } flag|=(last>tim); } } if(pd=="min") { if(last==-1) { cout<<(s.size()==0?0:(s.begin()->first-(s.begin()->second-1))%2)<<endl; } else { it=s.lower_bound(make_pair(last,0)); pre=prev(it); cout<<min(pre->first+1,last)<<endl; } } if(pd=="max") { if(maxx==0x7f7f7f7f) { cout<<"inf"<<endl; } else { cout<<maxx<<endl; } } } } fclose(stdin); fclose(stdout); return 0; }
\(T3\) C. 距离(distance) \(70pts\)
- 部分分
-
\(40pts\) :模拟,会被链卡到飞起,时间复杂度为 \(O(n^{3})\) 。
点击查看代码
const int p=1000000007; struct node { int nxt,to; }e[1000010]; int head[1000010],dfn[1000010],out[1000010],pos[1000010],a[1000010],b[1000010],cnt=0,tot=0; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x,int fa) { tot++; dfn[x]=tot; pos[tot]=x; for(int i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { dfs(e[i].to,x); } } out[x]=tot; } int qadd(int a,int b,int p) { return a+b>=p?a+b-p:a+b; } int main() { freopen("distance.in","r",stdin); freopen("distance.out","w",stdout); int n,u,v,ans=0,i,j,k; scanf("%d",&n); for(i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); } dfs(1,0); for(i=1;i<=n;i++) { ans=0; for(j=dfn[i];j<=out[i];j++) { for(k=dfn[i];k<=out[i];k++) { ans=qadd(ans,min(abs(a[pos[j]]-a[pos[k]]),abs(b[pos[j]]-b[pos[k]])),p); } } printf("%d\n",ans); } fclose(stdin); fclose(stdout); return 0; }
-
\(70pts\) :子树信息可以直接合并,每对点对之间的贡献只会被算一次,随便写个什么维护即可,时间复杂度为 \(O(n^{2})\) 。
点击查看代码
const int p=1000000007; struct node { int nxt,to; }e[1000010]; int head[500010],dfn[500010],out[500010],pos[500010],a[500010],b[500010],ans[500010],cnt=0,tot=0; vector<short>rt[10010]; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void merge(int x,int y) { if(rt[x].size()<rt[y].size()) { swap(rt[x],rt[y]); } for(int i=0;i<rt[y].size();i++) { rt[x].push_back(rt[y][i]); } } int qadd(int a,int b,int p) { return a+b>=p?a+b-p:a+b; } void dfs(int x,int fa) { tot++; dfn[x]=tot; pos[tot]=x; rt[x].push_back(x); for(int i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { dfs(e[i].to,x); ans[x]=qadd(ans[x],ans[e[i].to],p); for(int j=0;j<rt[e[i].to].size();j++) { for(int k=0;k<rt[x].size();k++) { ans[x]=qadd(ans[x],min(abs(a[rt[e[i].to][j]]-a[rt[x][k]]),abs(b[rt[e[i].to][j]]-b[rt[x][k]]))*2%p,p); } } merge(x,e[i].to); } } out[x]=tot; } int main() { freopen("distance.in","r",stdin); freopen("distance.out","w",stdout); int n,u,v,i; scanf("%d",&n); for(i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); } dfs(1,0); for(i=1;i<=n;i++) { printf("%d\n",ans[i]); } fclose(stdin); fclose(stdout); return 0; }
-
\(80pts\)
- 先将 \(\min(|a_{i}-a_{j}|,|b_{i}-b_{j}|)\) 容斥成 \(|a_{i}-a_{j}|+|b_{i}-b_{j}|-\max(|a_{i}-a_{j}|,|b_{i}-b_{j}|)\) ,难点在于怎么求后面的 \(\max(|a_{i}-a_{j}|,|b_{i}-b_{j}|)\) 。
- 将 \(\{ a \}\) 看做横坐标, \(\{ b \}\) 看做纵坐标,等价于询问切比雪夫坐标系下以 \(x\) 为根的子树内的节点两两距离之和。
- 考虑转化成曼哈顿距离,令 \(\forall i \in [i,n],p_{i}=\frac{a_{i}+b_{i}}{2},q_{i}=\frac{a_{i}-b_{i}}{2}\) ,则 \(\max\limits(|a_{i}-a_{j}|,|b_{i}-b_{j}|)=|p_{i}-p_{j}|+|q_{i}-q_{j}|\) ,等价于询问 \(\sum\limits_{i \in Subtree(x)}\sum\limits_{j \in Subtree(x)}|a_{i}-a_{j}|+|b_{i}-b_{j}|-|p_{i}-p_{j}|-|q_{i}-q_{j}|\) 。
- 拆绝对值,有 \(\begin{aligned} &|p_{i}-p_{j}|+|q_{i}-q_{j}| \\ &=\max\limits(p_{i}-p_{j},p_{j}-p_{i})+\max\limits(q_{i}-q_{j},q_{j}-q_{i}) \\ &=\max(\frac{a_{i}+b_{i}-a_{j}-b_{j}}{2},\frac{a_{j}+b_{j}-a_{i}-b_{i}}{2})+\max(\frac{a_{i}-b_{i}-a_{j}+b_{j}}{2},\frac{a_{j}-b_{j}-a_{i}+b_{i}}{2}) \\ &=\max(a_{i}-a_{j},a_{j}-a_{i},b_{i}-b_{j},b_{j}-b_{i}) \\ &=\max(|a_{i}-a_{j}|,|b_{i}-b_{j}|) \end{aligned}\) 。
- 以 \(\{ a \}\) 为例,用线段树对 \(\{ a \}\) 开一个桶数组。当插入一个新的数 \(a_{i}\) 时维护 \(<a_{i}, \ge a_{i}\) 的元素的数量及和,从而得到贡献。树上启发式合并的时间复杂度为 \(O(n \log^{2} n)\) 。
-
- 正解
-
而插入一个值时可能会与多个数产生贡献,考虑线段树合并。
-
具体地,对于以 \(x\) 为根的子树内的节点的值构成的有序数组 \(\{ a \}\) ,设 \(ans_{l,r},sum_{l,r},cnt_{l,r}\) 分别表示 \([l,r]\) 的贡献/元素和/元素数量,则有 \(ans_{l,r}=ans_{l,mid}+ans_{mid+1,r}+sum_{mid+1,r} \times cnt_{1,mid}-sum_{1,mid} \times cnt_{mid+1,n}\) 。向上递归时
pushup
即可。 -
时空复杂度为 \(O(n \log n)\) 。
点击查看代码
const ll mod=1000000007; struct node { int nxt,to; }e[1000010]; int head[500010],cnt=0; ll a[500010],aa[500010],b[500010],bb[500010],p[500010],pp[500010],q[500010],qq[500010],ans[500010]; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } struct SMT { int root[500010],rt_sum=0; struct SegmentTree { int ls,rs; ll sum,cnt,ans; }tree[500010*30]; #define lson(rt) (tree[rt].ls) #define rson(rt) (tree[rt].rs) void clear() { rt_sum=0; memset(root,0,sizeof(root)); } int build() { rt_sum++; lson(rt_sum)=rson(rt_sum)=tree[rt_sum].sum=tree[rt_sum].cnt=tree[rt_sum].ans=0; return rt_sum; } void pushup(int rt) { tree[rt].sum=(tree[lson(rt)].sum+tree[rson(rt)].sum)%mod; tree[rt].cnt=(tree[lson(rt)].cnt+tree[rson(rt)].cnt)%mod; tree[rt].ans=((tree[lson(rt)].ans+tree[rson(rt)].ans)%mod+tree[rson(rt)].sum*tree[lson(rt)].cnt%mod-tree[lson(rt)].sum*tree[rson(rt)].cnt%mod+mod)%mod; } void update(int &rt,int l,int r,int pos,int val) { rt=(rt==0)?build():rt; if(l==r) { tree[rt].cnt=(tree[rt].cnt+1)%mod; tree[rt].sum=(tree[rt].sum+val)%mod; return; } int mid=(l+r)/2; if(pos<=mid) { update(lson(rt),l,mid,pos,val); } else { update(rson(rt),mid+1,r,pos,val); } pushup(rt); } int merge(int rt1,int rt2,int l,int r) { if(rt1==0||rt2==0) { return rt1+rt2; } if(l==r) { tree[rt1].sum=(tree[rt1].sum+tree[rt2].sum)%mod; tree[rt1].cnt=(tree[rt1].cnt+tree[rt2].cnt)%mod; return rt1; } int mid=(l+r)/2; lson(rt1)=merge(lson(rt1),lson(rt2),l,mid); rson(rt1)=merge(rson(rt1),rson(rt2),mid+1,r); pushup(rt1); return rt1; } }T; void dfs(int x,int fa,ll d,ll a[],ll aa[]) { for(int i=head[x];i!=0;i=e[i].nxt) { if(e[i].to!=fa) { dfs(e[i].to,x,d,a,aa); T.root[x]=T.merge(T.root[x],T.root[e[i].to],1,aa[0]); } } T.update(T.root[x],1,aa[0],a[x],aa[a[x]]); ans[x]=(ans[x]+T.tree[T.root[x]].ans*d%mod+mod)%mod; } void solve(int n,ll d,ll a[],ll aa[]) { T.clear(); for(int i=1;i<=n;i++) { aa[i]=a[i]; } sort(aa+1,aa+1+n); aa[0]=unique(aa+1,aa+1+n)-(aa+1); for(int i=1;i<=n;i++) { a[i]=lower_bound(aa+1,aa+1+aa[0],a[i])-aa; } for(int i=1;i<=aa[0];i++) { aa[i]=(aa[i]+mod)%mod; } dfs(1,0,d,a,aa); } int main() { freopen("distance.in","r",stdin); freopen("distance.out","w",stdout); int n,u,v,i; ll inv=qpow(2,mod-2,mod); scanf("%d",&n); for(i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) { scanf("%lld%lld",&a[i],&b[i]); p[i]=a[i]+b[i]; q[i]=a[i]-b[i]; } solve(n,1,a,aa); solve(n,1,b,bb); solve(n,(mod-inv)%mod,p,qq); solve(n,(mod-inv)%mod,q,pp); for(i=1;i<=n;i++) { printf("%lld\n",ans[i]*2%mod); } fclose(stdin); fclose(stdout); return 0; }
-
\(T4\) D. 团队选拔(selection) \(8pts\)
-
部分分
-
子任务 \(1\) :爆搜。
点击查看代码
const ll p=998244353; ll a[100010],vis[100010],ans[100010]; ll qpow(ll a,ll b,ll p) { ll ans=1; while(b) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; } void dfs(ll pos,ll n,ll pre) { if(pos==n+1) { ll flag=1,pos=0,d=0,last=0; for(ll i=1;i<=n;i++) { if(vis[i]!=0) { last=gcd(last,a[i]); if(vis[i]!=vis[i+1]) { pos=i; break; } } } for(ll i=pos+1;i<=n;i++) { if(vis[i]!=0) { d=gcd(d,a[i]); if(vis[i]!=vis[i+1]) { flag&=(d==0||d==last); d=0; } } else { flag&=(d==0||d==last); d=0; } } if(flag==1) { for(ll i=1;i<=n;i++) { if(vis[i]!=0) { ans[i]=(ans[i]+1)%p; } } } } else { if(vis[pos-1]!=0) { vis[pos]=vis[pos-1]; dfs(pos+1,n,pos); } vis[pos]=vis[pre]+1; dfs(pos+1,n,pos); vis[pos]=0; dfs(pos+1,n,pre); } } int main() { freopen("selection.in","r",stdin); freopen("selection.out","w",stdout); ll n,i; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); } dfs(1,n,1); for(i=1;i<=n;i++) { printf("%lld ",ans[i]); } fclose(stdin); fclose(stdout); return 0; }
-
子任务 \(2\)
-
子任务 \(3,4\)
-
通过 luogu P3794 签到题IV 的经典结论,有当固定左端点 \(l\) 时 \(\gcd\limits_{i=l}^{r} \{ a_{i} \}\) 至多会变化 \(O(\log V)\) 次。
-
-
子任务 \(5\)
-
-
正解
点击查看官方题解代码
#include<bits/stdc++.h> #define LL long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) inline int read() { char c=getchar();int x=0;while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48,c=getchar();return x; } const int mod=998244353,maxn=100005; struct sode{int l,r,v;}st[maxn],bl[maxn]; struct node{int l,r,x,v;}A[maxn*30],B[maxn*30]; struct Seg{int l,r,v;}seg[2][maxn]; int gcd(int a,int b) {return !b?a:gcd(b,a%b);} inline int dqm(int x) {return x<0?x+mod:x;} inline int qm(int x) {return x>=mod?x-mod:x;} inline int cmp(const node &A,const node &B){ return A.v==B.v?A.x<B.x:A.v<B.v; } inline int ctp(const node &A,const node &B) { return A.v==B.v?A.x>B.x:A.v<B.v; } int n,a[maxn],top,sa,sb,lp,sz[2],ans,pre[maxn]; int l[maxn*3],r[maxn*3],tag[maxn*3],d[maxn*3]; inline void pushup(int i) {d[i]=qm(d[i<<1]+d[i<<1|1]);} inline void pushr(int i,int v) { tag[i]=v;d[i]=1ll*(r[i]-l[i]+1)*v%mod; } inline void pushdown(int i) { if(tag[i]==-1) return;pushr(i<<1,tag[i]); pushr(i<<1|1,tag[i]);tag[i]=-1; } void bud(int x,int y,int i) { l[i]=x,r[i]=y,tag[i]=-1;if(x==y) return; int mid=x+y>>1;bud(x,mid,i<<1),bud(mid+1,y,i<<1|1); } void chg(int x,int y,int v,int i) { if(x<=l[i]&&y>=r[i]) {pushr(i,v);return;} int mid=l[i]+r[i]>>1;pushdown(i); if(x<=mid) chg(x,y,v,i<<1); if(y>mid) chg(x,y,v,i<<1|1);pushup(i); } int qry(int x,int y,int i) { if(x<=l[i]&&y>=r[i]) return d[i]; int mid=l[i]+r[i]>>1;pushdown(i); return qm((x<=mid?qry(x,y,i<<1):0)+(y>mid?qry(x,y,i<<1|1):0)); } inline void ins(int l,int r,int v,int o) { if(r>n)r=n;if(l<1)l=1;if(l>r) return; seg[o][++sz[o]]=(Seg){l,r,v}; } inline void calc(int l,int r,int v) { pre[l]=qm(pre[l]+v),pre[r+1]=dqm(pre[r+1]-v); } inline void solve(int L,int R) { int lst=0,v=0;sz[0]=sz[1]=0; for(int i=L;i<=R;++i) { chg(lst,A[i].x-1,v,1); ins(lst+1,A[i].x,qm(v+1),0); lst=A[i].x; v=qm(v+qry(A[i].l-1,A[i].r-1,1)); v=qm(v+A[i].r-A[i].l+1); } chg(lst,n,v,1); ins(lst+1,n+1,qm(v+1),0); lst=n+1,v=0;int rp=lp; while(lp<=sb&&B[lp].v==A[L].v) ++lp; for(int i=rp;i<lp;++i) { chg(B[i].x+1,lst,v,1); ins(B[i].x,lst-1,qm(v+1),1); lst=B[i].x; v=qm(v+qry(B[i].l+1,B[i].r+1,1)); v=qm(v+B[i].r-B[i].l+1); } chg(1,lst,v,1);ans=qm(ans+v); ins(0,lst-1,qm(v+1),1); std::reverse(seg[1],seg[1]+sz[1]+1); int x,y;x=0,y=0; while(x<=sz[0]&&y<=sz[1]) { calc(max(seg[0][x].l,seg[1][y].l),min(seg[0][x].r,seg[1][y].r),dqm(1ll*seg[0][x].v*seg[1][y].v%mod-1)); if(seg[0][x].r<seg[1][y].r) ++x; else if(seg[0][x].r>seg[1][y].r) ++y; else if(seg[0][x].r==seg[1][y].r) ++y,++x; } } int main() { freopen("selection.in", "r", stdin); freopen("selection.out", "w", stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) { for(int j=1;j<=top;++j) st[j].v=gcd(st[j].v,a[i]); st[++top]=(sode){i,i,a[i]}; int tot=0,x=i,y=i; for(int j=top-1;j>=0;--j) { if(st[j].v!=st[j+1].v) { bl[++tot].l=x,bl[tot].r=y; bl[tot].v=st[j+1].v; x=st[j].l,y=st[j].r; }else x=st[j].l; } top=0; while(tot) st[++top]=bl[tot--]; for(int j=1;j<=top;++j) A[++sa]=(node){st[j].l,st[j].r,i,st[j].v}; } top=0; for(int i=n;i;i--) { for(int j=1;j<=top;++j) st[j].v=gcd(st[j].v,a[i]); st[++top]=(sode){i,i,a[i]}; int tot=0,x=i,y=i; for(int j=top-1;j>=0;--j) if(st[j].v!=st[j+1].v) { bl[++tot].l=x,bl[tot].r=y; bl[tot].v=st[j+1].v; x=st[j].l,y=st[j].r; } else y=st[j].r; top=0; while(tot) st[++top]=bl[tot--]; for(int j=1;j<=top;++j) B[++sb]=(node){st[j].l,st[j].r,i,st[j].v}; } std::sort(A+1,A+sa+1,cmp);std::sort(B+1,B+sb+1,ctp); int L=1;lp=1; bud(0,n+1,1); for(int i=2;i<=sa+1;++i) if(A[i].v!=A[i-1].v) solve(L,i-1),L=i; for(int i=1;i<=n;i++)pre[i]=qm(pre[i-1]+pre[i]); for(int i=1;i<=n;i++)printf("%d ",dqm(ans-pre[i])); return 0; }
总结
- \(T1\) 边权 $ \le k$ 的边界点初始值写错了,而且误认为 \(k-\max\limits_{x \in S}\{ x \}=\max\limits_{x \in S} \{ k-x \}\) ,挂了 \(60pts\) 。
- \(T2\) 写完后以为原来代码搞反了 \(p,q\) 的含义遂反转了过来,结果是原来代码没写反,挂了 \(9pts\) 。
- 写 \(T4\) 爆搜的时间用得太多了。
后记
- \(T2\) 的大样例下发文件里夹杂着 \(T4\) 的大样例, \(T4\) 的大样例下发文件里不知道是个什么东西。后来不知道什么时候把下发文件换了下。
- \(T1,T2,T4\) 均出自 [2024暑期交流小组] CSP-S & NOIP模拟赛 4 ,故直接搬的官方整个 PDF 题解; \(T3\) 单独下发了题解。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18468096,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。