我竟然独立切掉了这道题!incredible!
纪念我逝去的一上午(NOIP 总时长 4.5h,这题做了我整整 4.5h)
首先讲一下现场我想的 80 分的做法,虽然最后挂成了 65 分,但大概率是被卡常了(
注意到虽然点数高达 (prodlimits_{i=1}^kw_i),但每一维我们都可以单独考虑,具体来说,我们设 (tim_{i,j}) 表示只考虑 (c_k=i) 的 (k),当前第 (i) 维坐标是 (j),最少需要多少步才能离开场地,(tim_{i,j}) 显然 xjb 分类讨论就能求出。那么由于每一维的独立性,对于一个坐标 ((x_1,x_2,cdots,x_k)),它所需要的离开场地的最小时间就是对应每一维所需时间取 (min),即 (minlimits_{i=1}^ktim_{i,x_i}),也就是说我们要求的东西就是 (sumlimits_{x_ile w_i}minlimits_{i=1}^ktim_{i,x_i}),我们考虑将 (tim_{i,j}) 全部揉在一起从大到小排序并枚举 (minlimits_{i=1}^ktim_{i,x_i}=tim_{x,y}),那么此时合法的坐标数目就是 (prodlimits_{j
e x}cnt_j),其中 (cnt_j=sumlimits_{k=1}^{w_j}[tim_{j,k}>tim_{x,y}]),这个值可以通过预处理逆元在枚举的过程中 (mathcal O(1)) 求得。那么,加上排序的复杂度,总复杂度大概是 (nklog nk)。然鹅这个复杂度不开 O2 是过不去的,有我现场写的程序为证。因此考虑加点小小的剪枝,注意到 (tim_{i,j}) 随着 (j) 的增大是一个凸函数,因此咱考虑找到该函数的峰点,然后将两部分归并起来即可在 (mathcal O(w_i)) 的时间内将某个 (tim_{i}) 从大到小排序,然后再将所有 (tim_i) 再归并起来即可。然鹅有一个让人非常哭笑不得的细节,就是在对全部 (k) 个数组归并时,找最小值用 priority_queue
,时间复杂度 (mathcal O(nklog k)) 反而 TLE,改成暴力 (mathcal O(k)) 找反而就过了,大概是常数的问题吧。
附:80 分的代码:
const int MAXN=5e5;
const int MAXK=10;
const int MOD=1e9+7;
int n,k,c[MAXN+5],d[MAXN+5],w[MAXK+2];
namespace sub1{
bool check(){
int flg=1;
for(int i=1;i<=k;i++) flg&=(w[i]<=1e6);
return flg;
}
const int MAXW=1e6;
const ll INF=0x3f3f3f3f3f3f3f3fll;
ll tim[MAXK+2][MAXW+5];
int lft[MAXW+5],rit[MAXW+5];
void calc(int x){
memset(lft,0,sizeof(lft));memset(rit,0,sizeof(rit));
int mn=0,mx=0,cur=0;
for(int i=1;i<=n;i++) if(c[i]==x) cur+=d[i];
if(cur<0){
for(int i=1;i<=n;i++) if(c[i]==x) d[i]=-d[i];
} cur=0;
for(int i=1;i<=n;i++) if(c[i]==x){
cur+=d[i];
if(cur>mx) rit[cur]=i,mx=cur;
if(cur<mn) lft[-cur]=i,mn=cur;
}
for(int i=1;i<=w[x];i++){
tim[x][i]=INF;
if(i+mn<=0) chkmin(tim[x][i],(ll)lft[i]);
if(i+mx>w[x]) chkmin(tim[x][i],(ll)rit[w[x]+1-i]);
if(cur){
int bound=w[x]-mx+1;
int tt=max((bound-i+cur-1)/cur,0);
chkmin(tim[x][i],1ll*tt*n+rit[w[x]+1-(i+tt*cur)]);
}
}
} ll A[MAXW+5],B[MAXW+5];
int inv[MAXW+5];
void mergesort(int x){
int ps=0,c1=0,c2=0;
for(int i=1;i<=w[x];i++) if(tim[x][i]>tim[x][i+1]){ps=i;break;}
for(int i=ps;~i;i--) A[++c1]=tim[x][i];A[c1+1]=0;
for(int i=ps+1;i<=w[x];i++) B[++c2]=tim[x][i];B[c2+1]=0;
for(int i=1,p1=1,p2=1;i<=w[x];i++){
if(A[p1]>B[p2]) tim[x][i]=A[p1++];
else tim[x][i]=B[p2++];
}
}
int cnt[MAXK+5];
void solve(){
for(int i=1;i<=k;i++) calc(i);
for(int i=1;i<=k;i++) mergesort(i);
for(int i=(inv[0]=inv[1]=1)+1;i<=MAXW;i++)
inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
int sm=0;for(int i=1;i<=k;i++) sm+=w[i];
bool flg=1;
for(int i=1;i<=k;i++) flg&=(tim[i][1]==INF);
if(flg) return puts("-1"),void();
int res=1,cnt0=k,ans=0;
for(int i=1;i<=sm;i++){
int x=0;
for(int j=1;j<=k;j++) if(tim[j][cnt[j]+1]>tim[x][cnt[x]+1]) x=j;
if(!cnt[x]) cnt0--;
else res=1ll*res*inv[cnt[x]]%MOD*(cnt[x]+1)%MOD;
++cnt[x];
if(!cnt0&&tim[x][cnt[x]]) ans=(ans+tim[x][cnt[x]]%MOD*res%MOD*inv[cnt[x]])%MOD;
} printf("%d
",ans);
}
}
int main(){
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&d[i]);
if(sub1::check()) sub1::solve();
return 0;
}
接下来考虑正解,也就是这个脑子不太好使的人今早灵机一动想出来的做法。
我们考虑预处理出这样几个量:
- (x_i):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么在一个周期中第 (i) 维坐标的最小值是多少。
- (y_i):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么在一个周期中第 (i) 维坐标的最大值是多少。
- (t_i):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么在一个周期结束后第 (i) 维的坐标是多少。方便起见我们假设 (t_ige 0),如果 (t_i<0) 那我们只需将 (c_j=i) 的 (d_j) 都变为其相反数即可。
- (mn_{i,j}):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么执行完前 (j) 个命令后,在一个周期中第 (i) 维坐标的最小值是多少,不难发现 (x_i=mn_{i,n})。
- (mx_{i,j}):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么执行完前 (j) 个命令后,在一个周期中第 (i) 维坐标的最大值是多少,同样地有 (y_i=mx_{i,n})。
- (sum_{i,j}):在一整个长度为 (n) 周期中,如果我们将起点视为源点,那么执行完前 (j) 个命令后,第 (i) 维的坐标是多少。
首先我们思考一下对于某一维 (i) 上的某个坐标 (x),最少需要多少步才能离开这一维的范围(即,这一维的坐标 ( otin[1,w_i]))。一个比较显然但非常关键的性质是,由于 (t_ige 0),因此如果第一个周期内不能从左边离开场地,那么第二周期起点位置肯定比第一周期更靠右,也就更不可能从右边离开场地,也就是说如果离开时走的步数 (>n),那么我们必定是从右边离开场地的。因此我们考虑枚举小 C 最后一步是在这个长度为 (n) 的周期中哪个指令下离开场地,记为第 (i) 个命令。那么此时此刻已经执行的命令必定是若干个长度为 (n) 的完整的周期加上前 (i) 个命令构成的这段前缀,我们记当前位于第 (K) 个周期(方便起见我们不妨设 (Kge 2),(K=1) 的情况后面再说),那么根据之前的推论,这一步肯定是第 (c_i) 维坐标达到了 (w_{c_i}+1)。又因为第一周期内无法离开场地,因此如果我们记 (s_i) 为第 (i) 起点的坐标,必定有 (s_jin[-x_j+1,w_j]),又因为在前 ((K-1)n+i-1) 步内不能离开场地,因此对于每一维 (j) 可以列出以下四个不等式:
再加上第 (i) 步第 (c_i) 维坐标需达到 (w_{c_i}+1),因此还有 (s_{c_i}+(K-1)t_{c_i}+sum_{c_i,i-1}=w_{c_i}+1)。
总共是 (5k+1) 个限制,每个限制都可以表示为 (s_jin[L,R]) 的形式,因此我们可以解出 (s_j) 的范围,如果存在某个 (s_j) 的范围为空则表明不可能恰好在第 ((K-1)n+i) 步离开场地,否则合法的坐标数就是 (s_j) 范围的乘积。
但是直接枚举 (K) 复杂度过高,无法接受。不过注意到一个性质就是如果存在某个坐标经过 (Kn+i) 步离开场地,就必定存在某个坐标经过 ((K-1)n+i) 步离开场地,因此考虑二分最大的 (K) 满足存在某个坐标经过 ((K-1)n+i) 步离开场地,那么我们要求的值就是 (sumlimits_{j=2}^K ext{calc}((j-1)n+i)·((j-1)n+i)),其中 ( ext{calc}(x)) 为满足恰好经过 (x) 步离开场地的坐标个数。暴力算还是 T,不过我们还可以发现,每次解出来的 (s_j(j e c_i)) 的范围区间的左端点都是固定不变的值 (-x_j+1),因此区间长度可以写成关于右端点的一次函数,又区间非空,因此右端点可以写成关于 (K) 的一次函数,因此 ( ext{calc}((j-1)n+i)) 可以看作关于 (j) 的 (k-1) 次函数,再加上前缀和与后面的系数,(sum) 里的东西为关于 (K) 的 (k+1) 次函数,因此可以考虑求出 (2,3,cdots,k+3) 处的函数值然后把多项式插出来即可。
接下来考虑 (K=1) 的情况,相信聪明的读者们如果理解了 (Kge 2) 的情况,那么 (K=1) 的情况想必是易如反掌了,我们还是可以列出一些关于 (s_j) 的不等式,也就能解出对应 (s_j) 的范围,然后可以乘法原理对应的坐标个数,如果还是不懂那就看代码吧。
上述算法复杂度是 (nklog n+nk^2),不开 O2 只能获得 80 分的好成绩。
附:不开 O2 80pts,开 O2 AC 的代码:
namespace sub2{
int x[MAXK+2],y[MAXK+2],t[MAXK+2];
int mn[MAXK+2][MAXN+5],mx[MAXK+2][MAXN+5],sum[MAXK+2][MAXN+5];
void calc(int r){
for(int i=1;i<=n;i++) if(c[i]==r) t[r]+=d[i];
if(t[r]<0){
t[r]=-t[r];
for(int i=1;i<=n;i++) if(c[i]==r) d[i]=-d[i];
} int cur=0;
for(int i=1;i<=n;i++){
if(c[i]==r) cur+=d[i];sum[r][i]=cur;
mn[r][i]=min(mn[r][i-1],cur);
mx[r][i]=max(mx[r][i-1],cur);
} x[r]=mn[r][n];y[r]=mx[r][n];
// printf("%d %d
",x[r],y[r]);
}
struct itvl{
ll l,r;
itvl(ll _l=0,ll _r=0):l(_l),r(_r){}
itvl operator &(const itvl &rhs){
return itvl(max(l,rhs.l),min(r,rhs.r));
}
};
int calc(int mid,int id){
static itvl it[MAXK+2];
for(int i=1;i<=k;i++) it[i]=itvl(-x[i]+1,w[i]);
for(int i=1;i<=k;i++){
it[i]=it[i]&itvl(1-1ll*(mid-2)*t[i]-y[i],w[i]-1ll*(mid-2)*t[i]-y[i]);
it[i]=it[i]&itvl(1-1ll*(mid-1)*t[i]-mx[i][id-1],w[i]-1ll*(mid-1)*t[i]-mx[i][id-1]);
} it[c[id]]=it[c[id]]&itvl(w[c[id]]+1-1ll*(mid-1)*t[c[id]]-sum[c[id]][id],w[c[id]]+1-1ll*(mid-1)*t[c[id]]-sum[c[id]][id]);
// printf("checking %d %d
",mid,id);
// for(int i=1;i<=k;i++) printf("%lld %lld
",it[i].l,it[i].r);
int res=1;
for(int i=1;i<=k;i++){
if(it[i].l>it[i].r) return 0;
res=1ll*res*(it[i].r-it[i].l+1)%MOD;
} return res;
}
int ff[10],inv[10];
void solve(){
for(int i=(inv[0]=inv[1]=1)+1;i<=6;i++) inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=k;i++) calc(i);
// for(int i=1;i<=k;i++) printf("%d %d %d
",x[i],y[i],t[i]);
int res=0;
for(int i=1;i<=n;i++) if(d[i]==1){
int l=2,r=1e9,p=-1;
if(calc(1e9+1,i)) return puts("-1"),void();
while(l<=r){
int mid=l+r>>1;
if(calc(mid,i)) p=mid,l=mid+1;
else r=mid-1;
} //printf("%d
",p);
if(~p){
for(int j=2;j<=min(p,6);j++){
// printf("%d %d %d
",j,i,calc(j,i));
ff[j]=1ll*calc(j,i)*(1ll*(j-1)*n%MOD+i)%MOD;
ff[j]=(ff[j-1]+ff[j])%MOD;
} if(p<=6) res=(res+ff[p])%MOD;
else{
for(int j=2;j<=6;j++){
int ss=1;
for(int k=2;k<=6;k++) if(j^k){
int mul=1ll*(p-k+MOD)*inv[abs(j-k)]%MOD;
if(j<k) mul=MOD-mul;ss=1ll*ss*mul%MOD;
} res=(res+1ll*ss*ff[j])%MOD;
}
}
}
}
for(int i=1;i<=n;i++){
static itvl it[MAXK+2];
for(int j=1;j<=k;j++) it[j]=itvl(1,w[j]);
for(int j=1;j<=k;j++){
it[j]=it[j]&itvl(1-mn[j][i-1],w[j]-mn[j][i-1]);
it[j]=it[j]&itvl(1-mx[j][i-1],w[j]-mx[j][i-1]);
} if(!~d[i]){
it[c[i]]=it[c[i]]&itvl(0-sum[c[i]][i],0-sum[c[i]][i]);
} else {
it[c[i]]=it[c[i]]&itvl(w[c[i]]+1-sum[c[i]][i],w[c[i]]+1-sum[c[i]][i]);
} int mul=i;
// printf("%d:
",i);
// for(int j=1;j<=k;j++) printf("%lld %lld
",it[j].l,it[j].r);
for(int j=1;j<=k;j++){
if(it[j].l>it[j].r) mul=0;
else mul=1ll*mul*(it[j].r-it[j].l+1)%MOD;
} res=(res+mul)%MOD;
}
printf("%d
",res);
}
}
int main(){
// freopen("walk4.in","r",stdin);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&d[i]);
if(sub1::check()) sub1::solve();
else sub2::solve();
return 0;
}
接下来考虑加点优化,显然复杂度瓶颈在于二分,注意到在二分检验的过程中,我们要用到很多不等式,不过这些不等式都可以写成 (s_jin[1-Kt_j+B,w_j-Kt_j+B]) 的形式,又根据之前的推理这些区间的交的左端点恰好是 (-x_j+1),因此我们只用考虑右端点的限制,即 (B) 最小的限制即可,由于这些区间的交集非空,必然可以得到 (w_j-Kt_j+Bge -x_j+1),移个项可以得到 (Kt_jle w_j+B+x_j-1),解得 (Klelfloordfrac{w_j+B+x_j-1}{t_j} floor),也就是说这些限制归结到底都可以写成 (Kle X) 的形式,然后对这些 (X) 取个 (min) 即可得到 (K) 的最大值,这样就省去了二分的 (log)。
还有就是上面的代码中插值用了暴力 (k^2) 的插值方法,不过由于下标连续,可以 (mathcal O(k)) 插值,这样常数会小不少。
最后附上我最后一次提交的完整代码,开了 O2 只需 947ms:
const int MAXN=5e5;
const int MAXK=10;
const int MOD=1e9+7;
int n,k,c[MAXN+5],d[MAXN+5],w[MAXK+2];
namespace sub1{
bool check(){
int flg=1;
for(int i=1;i<=k;i++) flg&=(w[i]<=1e6);
return flg;
}
const int MAXW=1e6;
const ll INF=0x3f3f3f3f3f3f3f3fll;
ll tim[MAXK+2][MAXW+5];
int lft[MAXW+5],rit[MAXW+5];
void calc(int x){
memset(lft,0,sizeof(lft));memset(rit,0,sizeof(rit));
int mn=0,mx=0,cur=0;
for(int i=1;i<=n;i++) if(c[i]==x) cur+=d[i];
if(cur<0){
for(int i=1;i<=n;i++) if(c[i]==x) d[i]=-d[i];
} cur=0;
for(int i=1;i<=n;i++) if(c[i]==x){
cur+=d[i];
if(cur>mx) rit[cur]=i,mx=cur;
if(cur<mn) lft[-cur]=i,mn=cur;
}
for(int i=1;i<=w[x];i++){
tim[x][i]=INF;
if(i+mn<=0) chkmin(tim[x][i],(ll)lft[i]);
if(i+mx>w[x]) chkmin(tim[x][i],(ll)rit[w[x]+1-i]);
if(cur){
int bound=w[x]-mx+1;
int tt=max((bound-i+cur-1)/cur,0);
chkmin(tim[x][i],1ll*tt*n+rit[w[x]+1-(i+tt*cur)]);
}
}
} ll A[MAXW+5],B[MAXW+5];
int inv[MAXW+5];
void mergesort(int x){
int ps=0,c1=0,c2=0;
for(int i=1;i<=w[x];i++) if(tim[x][i]>tim[x][i+1]){ps=i;break;}
for(int i=ps;~i;i--) A[++c1]=tim[x][i];A[c1+1]=0;
for(int i=ps+1;i<=w[x];i++) B[++c2]=tim[x][i];B[c2+1]=0;
for(int i=1,p1=1,p2=1;i<=w[x];i++){
if(A[p1]>B[p2]) tim[x][i]=A[p1++];
else tim[x][i]=B[p2++];
}
}
int cnt[MAXK+5];
void solve(){
for(int i=1;i<=k;i++) calc(i);
for(int i=1;i<=k;i++) mergesort(i);
for(int i=(inv[0]=inv[1]=1)+1;i<=MAXW;i++)
inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
int sm=0;for(int i=1;i<=k;i++) sm+=w[i];
bool flg=1;
for(int i=1;i<=k;i++) flg&=(tim[i][1]==INF);
if(flg) return puts("-1"),void();
int res=1,cnt0=k,ans=0;
for(int i=1;i<=sm;i++){
int x=0;
for(int j=1;j<=k;j++) if(tim[j][cnt[j]+1]>tim[x][cnt[x]+1]) x=j;
if(!cnt[x]) cnt0--;
else res=1ll*res*inv[cnt[x]]%MOD*(cnt[x]+1)%MOD;
++cnt[x];
if(!cnt0&&tim[x][cnt[x]]) ans=(ans+tim[x][cnt[x]]%MOD*res%MOD*inv[cnt[x]])%MOD;
} printf("%d
",ans);
}
}
namespace sub2{
int x[MAXK+2],y[MAXK+2],t[MAXK+2];
int mn[MAXK+2][MAXN+5],mx[MAXK+2][MAXN+5],sum[MAXK+2][MAXN+5];
void calc(int r){
for(int i=1;i<=n;i++) if(c[i]==r) t[r]+=d[i];
if(t[r]<0){
t[r]=-t[r];
for(int i=1;i<=n;i++) if(c[i]==r) d[i]=-d[i];
} int cur=0;
for(int i=1;i<=n;i++){
if(c[i]==r) cur+=d[i];sum[r][i]=cur;
mn[r][i]=min(mn[r][i-1],cur);
mx[r][i]=max(mx[r][i-1],cur);
} x[r]=mn[r][n];y[r]=mx[r][n];
}
struct itvl{
ll l,r;
itvl(ll _l=0,ll _r=0):l(_l),r(_r){}
itvl operator &(const itvl &rhs){
return itvl(max(l,rhs.l),min(r,rhs.r));
}
};
int calc(int mid,int id){
static itvl it[MAXK+2];
for(int i=1;i<=k;i++) it[i]=itvl(-x[i]+1,w[i]);
for(int i=1;i<=k;i++){
it[i]=it[i]&itvl(1-1ll*(mid-2)*t[i]-y[i],w[i]-1ll*(mid-2)*t[i]-y[i]);
it[i]=it[i]&itvl(1-1ll*(mid-1)*t[i]-mx[i][id-1],w[i]-1ll*(mid-1)*t[i]-mx[i][id-1]);
} it[c[id]]=it[c[id]]&itvl(w[c[id]]+1-1ll*(mid-1)*t[c[id]]-sum[c[id]][id],w[c[id]]+1-1ll*(mid-1)*t[c[id]]-sum[c[id]][id]);
int res=1;
for(int i=1;i<=k;i++){
if(it[i].l>it[i].r) return 0;
res=1ll*res*(it[i].r-it[i].l+1)%MOD;
} return res;
}
int ff[15],ifac[15],pre[15],suf[15];
void solve(){
for(int i=(ifac[0]=ifac[1]=1)+1;i<=k+3;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=k+3;i++) ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
for(int i=1;i<=k;i++) calc(i);
bool flg=1;
for(int i=1;i<=k;i++) flg&=(!t[i]&&y[i]-x[i]+1<=w[i]);
if(flg) return puts("-1"),void();
int res=0;
for(int i=1;i<=n;i++) if(d[i]==1){
if(!calc(2,i)) continue;
int p=1e9+1;
for(int j=1;j<=k;j++){
if(t[j]){
chkmin(p,(w[j]+2*t[j]-y[j]+x[j]-1)/t[j]);
chkmin(p,(w[j]+t[j]-mx[j][i-1]+x[j]-1)/t[j]);
}
}
// while(l<=r){
// int mid=l+r>>1;
// if(calc(mid,i)) p=mid,l=mid+1;
// else r=mid-1;
// }
for(int j=2;j<=min(p,k+3);j++){
ff[j]=1ll*calc(j,i)*(1ll*(j-1)*n%MOD+i)%MOD;
ff[j]=(ff[j-1]+ff[j])%MOD;
} if(p<=k+3) res=(res+ff[p])%MOD;
else{
pre[1]=suf[k+4]=1;
for(int j=2;j<=k+3;j++) pre[j]=1ll*pre[j-1]*(p-j+MOD)%MOD;
for(int j=k+3;j>>1;j--) suf[j]=1ll*suf[j+1]*(p-j+MOD)%MOD;
for(int j=2;j<=k+3;j++){
int mul=1ll*pre[j-1]*suf[j+1]%MOD;
mul=1ll*mul*ifac[j-2]%MOD*ifac[k+3-j]%MOD;
if((k+3-j)&1) mul=MOD-mul;
res=(res+1ll*mul*ff[j])%MOD;
}
}
}
for(int i=1;i<=n;i++){
static itvl it[MAXK+2];
for(int j=1;j<=k;j++) it[j]=itvl(1,w[j]);
for(int j=1;j<=k;j++){
it[j]=it[j]&itvl(1-mn[j][i-1],w[j]-mn[j][i-1]);
it[j]=it[j]&itvl(1-mx[j][i-1],w[j]-mx[j][i-1]);
} if(!~d[i]) it[c[i]]=it[c[i]]&itvl(0-sum[c[i]][i],0-sum[c[i]][i]);
else it[c[i]]=it[c[i]]&itvl(w[c[i]]+1-sum[c[i]][i],w[c[i]]+1-sum[c[i]][i]);
int mul=i;
for(int j=1;j<=k;j++){
if(it[j].l>it[j].r) mul=0;
else mul=1ll*mul*(it[j].r-it[j].l+1)%MOD;
} res=(res+mul)%MOD;
}
printf("%d
",res);
}
}
int main(){
// freopen("walk4.in","r",stdin);
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&d[i]);
if(sub1::check()) sub1::solve();
else sub2::solve();
return 0;
}
啊啊啊啊啊啊啊我的 E 队怎么就没了呢