第一次考$NOIP$的我已经自闭了


$CCF$告诉我们了一件事情,要对自己写的程序有信仰,相信$CCF$的数据是水的

普及组:

分数:$100+100+30+100=330$

$1.titile$:

$cin$,$scanf$都试了试,却没有$A$掉第二个样例,最后$getchar()$$5$次$A$掉了

考场上加了一句读掉换行就停止,要是不加就会$WA$的很惨

$5$次$getchar()$,遇见换行停止

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int ans=,tot;
int main(){
freopen("title.in","r",stdin);
freopen("title.out","w",stdout);
while(tot<=){
char str=getchar();
if(int(str)==) break;
if((str>=''&&str<='')||(str>='a'&&str<='z')||(str>='A'&&str<='Z')) ans++;
tot++;
}
cout<<ans;
return ;
}

$2.fight$:

自闭了,被卡精度,简单的$O(n)$暴力。

$update$:$CCF$的数据是真水啊,好像开$int$过掉了

直接暴力枚举加入之后的势力就行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define int long long
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int m,p1,s1,s2,pos,n,a[],sum1,sum2,minn,inf=<<-;
signed main(){
freopen("fight.in","r",stdin);
freopen("fight.out","w",stdout);
n=read();
for(int i=;i<=n;i++) a[i]=read();
m=read(),p1=read(),s1=read(),s2=read();
a[p1]+=s1;
for(int i=;i<m;i++) sum1+=(m-i)*a[i];
for(int i=m+;i<=n;i++) sum2+=(i-m)*a[i];
minn=abs(sum2-sum1);
pos=m;
for(int i=;i<=n;i++){
int ans1=sum1,ans2=sum2;
if(i<m) ans1+=(m-i)*s2;
if(i>m) ans2+=(i-m)*s2;
int k=abs(ans1-ans2);
if(k<minn){minn=k,pos=i;}
}
cout<<pos;
return ;
}

$3.bus$:

观察$n$与$m$的范围,应该是一个二维$dp$,所以我们令$dp(i,j)$表示时间为$a[i]+j$,第$i$个人上车的等候总和,所以可以分两种情况考虑

1.当第$i$个人与第$i-1$个人不坐同一辆车时,则$dp(i,j)=max(dp(i,j),dp(i-1,k)+j)$

2.当第$i$个人愿意去并且与第$i-1$个人坐同一辆车则$dp(i,j)=max(dp(i,j),dp(i-1,k)+j)$

主要是对两种情况的判断

详情见代码

考场上其实写的是$dp(i,j)$为第$i$个人,当前时间为$j$且第$i$个人上车的等车情况,最后挂了,时间巨大

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int MAXN=;
const int MAXM=;
int N,M,A[MAXN],f[MAXN][MAXM],INF=INT_MAX;
int main(){
freopen("bus.in","r",stdin);
freopen("bus.out","w",stdout);
memset(f,/,sizeof(f));
N=read(),M=read();for(int i=;i<=N;i++) A[i]=read();sort(A+,A+N+);
for(int i=;i<M;i++) f[][i]=i;
for(int i=;i<=N;i++){
for(int j=;j<*M;j++){
if(j+A[i]-A[i-]>=&&j+A[i]-A[i-]<*M) f[i][j]=f[i-][j+A[i]-A[i-]]+j;
for(int p=;p<*M;p++){
int T=j+A[i],t1=p+A[i-]+M;if(t1>T) continue;
f[i][j]=min(f[i][j],f[i-][p]+j);
}
}
}
int Minn=INF;
for(int i=;i<*M;i++) Minn=min(Minn,f[N][i]);
printf("%d\n",Minn);return ;
}

$4.tree$:

搜索。

因为树是满足条件的必须

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int MAXN=;
struct node{
int siz,id;
}f[MAXN];
int L[MAXN],R[MAXN],siz[MAXN],N,A[MAXN],d[MAXN],rt;
void dfs1(int u){
siz[u]=;
if(L[u]) dfs1(L[u]),siz[u]+=siz[L[u]];
if(R[u]) dfs1(R[u]),siz[u]+=siz[R[u]];
return;
}
bool cmp(node x1,node x2){return x1.siz>x2.siz;}
bool checker(int u,int v){
if(!u&&!v) return ;
if(siz[u]!=siz[v]) return ;
if(A[u]!=A[v]) return ;
return checker(L[u],R[v])&&checker(R[u],L[v]);
}
int main(){
N=read();
for(int i=;i<=N;i++) A[i]=read();
for(int i=;i<=N;i++){
L[i]=read(),R[i]=read();
if(L[i]==-) L[i]=;if(R[i]==-) R[i]=;
d[L[i]]++,d[R[i]]++;
}
for(int i=;i<=N;i++) if(!d[i]){rt=i;break;}dfs1(rt);
for(int i=;i<=N;i++) f[i].siz=siz[i],f[i].id=i;sort(f+,f+N+,cmp);
for(int i=;i<=N;i++){
int tr=f[i].id;
if(checker(L[tr],R[tr])){printf("%d\n",f[i].siz);return ;}
}return ;
}

提高组:

分数:

day1:$100+0+55=155$

day2:$100+60+44=204$

$day1+day2=359$

$1.road$

差分即可,将序列差分以后可以看成将一个位置 $+1$ ,一个位置 $-1$,直接统计 $+1$ 块即可,因为可以将 $+1$ 块与 $-1$ 块匹配。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int cnt=;
struct node{
int l,r;
}x[];
int n,a[],sum;
signed main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
n=read();
for(int i=;i<=n;i++) a[i]=read();
x[].l=;
for(int i=;i<=n;i++){
if(a[i]>a[i-]) x[cnt].r=i-,x[++cnt].l=i;
}
int minn=;
x[cnt].r=n;
for(int i=;i<=cnt;i++){
sum+=(a[x[i].l]-minn);
minn=a[x[i].r];
}
cout<<sum;
return ;
}

$2.money$

考虑$n=2$的情况入手,发现若只能取一个就必须一个是另一个的倍数,然后我们就可以大胆猜想答案的货币系统一定是其原先货币系统的子集,然后经过简单思考发现这个结论是对的。

然后就是一个十分水的背包$dp$了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int T,a[],n,ans,M;
bool dp[];
int main()
{
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
T=read();
while(T--){
n=read();
ans=;
for(int i=;i<=n;i++) a[i]=read();
sort(a+,a+n+);
M=a[n];
memset(dp,,sizeof(dp));
dp[]=;
for(int i=;i<=n;i++){
if(!dp[a[i]]){
ans++;
for(int j=a[i];j<=M;j++) dp[j]|=dp[j-a[i]];
}
}
cout<<ans<<endl;
}
}

$3.track$

主要的思想就是选择两个子孙链上的进行合并,然后在不能合的里面选择最大的一条往上传即可。正确性显然。$multiset$ 维护一下即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<set>
#define int long long
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int MAXN=;
multiset<int> s[MAXN];
int n,k;
struct node{
int u,v,w,nex;
}x[MAXN<<];
int ans,l,r,head[MAXN],cnt,maxn;
void add(int u,int v,int w){
x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
}
int dfs(int xx,int fath,int lim){
s[xx].clear();
for(int i=head[xx];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
int val=dfs(x[i].v,xx,lim)+x[i].w;
if(val>=lim) ans++;
else s[xx].insert(val);
}
int maxn=;
while(!s[xx].empty()){
if(s[xx].size()==) return max(maxn,*s[xx].begin());
multiset<int> :: iterator it=s[xx].lower_bound(lim-*s[xx].begin());
if(it==s[xx].begin()&&s[xx].count(*it)==) it++;
if(it==s[xx].end()){
maxn=max(maxn,*s[xx].begin());
s[xx].erase(s[xx].find(*s[xx].begin()));
}else{
ans++;
s[xx].erase(s[xx].find(*s[xx].begin()));
s[xx].erase(s[xx].find(*it));
}
}
return maxn;
}
bool check(int xx){
ans=;
dfs(,,xx);
return ans>=k;
}
int dis[MAXN];
void dfs1(int f,int fath){
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
dis[x[i].v]=dis[f]+x[i].w;
dfs1(x[i].v,f);
}
return;
}
int get_dis(){
dfs1(,);
int maxn=,pos;
for(int i=;i<=n;i++){
if(dis[i]>maxn){
maxn=dis[i],pos=i;
}
}
dfs1(pos,);
maxn=;
for(int i=;i<=n;i++) maxn=max(maxn,dis[i]);
return maxn;
}
signed main(){
freopen("track.in","r",stdin);
freopen("track.out","w",stdout);
memset(head,-,sizeof(head));
n=read(),k=read();
for(int i=;i<n;i++){
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
r=get_dis();
while(l<=r){
int mid=l+r>>;
if(check(mid)) l=mid+,maxn=max(maxn,mid);
else r=mid-;
}
cout<<maxn;
}

$4.travel$

$update$:$CCF$的数据是真水啊,好像$O(n^2\times m)$过掉了

树的做法很简单吧,当遍历到节点$i$时,继续$dfs$编号最小且此节点的父亲是$i$的,$dfs$是因为与题意相符,回溯与往下。

当是个基环树的时候,我们可以发现其实有一条边是没有做过的,就去每次暴力删边,然后将每次的字典序记录下来,最后输出最小字典序即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,nex;
}x[];
int head[];
int cnt,n,m;
void add(int u,int v){
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int st[];
bool vis[];
int delu,delv,tot;
int da[];
int pig;
int kk[][];
int scc,cntcnt[],pos;
void dfs(int f,int fath){
if(pig==) return;
int son=;
int sry=;
while(sry<cntcnt[f]){
++sry;
pos=kk[f][sry];
if(vis[pos]) continue;
if((f==delu&&pos==delv)||(f==delv&&pos==delu)) continue;
vis[pos]=;
st[++st[]]=pos;
if(st[st[]]>da[st[]]&&pig!=){pig=;return;}
if(st[st[]]<da[st[]]){pig=;}
dfs(pos,f);
}
return;
}
struct node1{
int u,v;
}se[];
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
memset(da,/,sizeof(da));
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++){
int u=read(),v=read();
add(u,v),add(v,u);
se[i].u=u,se[i].v=v;
}
for(int i=;i<=n;i++){
for(int j=head[i];j!=-;j=x[j].nex){
kk[i][++cntcnt[i]]=x[j].v;
}
sort(kk[i]+,kk[i]+cntcnt[i]+);
}
delu=-,delv=-;
if(m==n-){
st[]=;
st[st[]]=;
vis[]=;
dfs(,);
for(int i=;i<=st[];i++) cout<<st[i]<<" ";
return ;
}
else{
for(int i=;i<=m;i++){
pig=;
memset(vis,,sizeof(vis));
delu=se[i].u,delv=se[i].v;
st[]=;
st[]=;
vis[]=;
dfs(,);
if(st[]!=n) continue;
bool ff=;
for(int j=;j<=n;j++){
if(st[j]>da[j]){ff=;break;}
if(st[j]<da[j]){ff=;break;}
}
if(ff)
for(int j=;j<=n;j++) da[j]=st[j]; }
for(int j=;j<=n;j++) printf("%d ",da[j]);
return ;
}
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,nex;
}x[];
int head[];
int cnt,n,m,inf=;
void add(int u,int v){
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int st[],vis[],delu,delv,tot;
int da[];
int pig;
void dfs(int f,int fath){
if(pig==) return;
int son=;
for(int i=head[f];i!=-;i=x[i].nex){
if((delu==f&&delv==x[i].v)||(delu==x[i].v&&delv==f)) continue;
if(x[i].v==fath) continue;
if(vis[x[i].v]) continue;
if((delu==f&&delv==x[i].v)||(delu==x[i].v&&delv==f)) continue;
if(x[i].v==fath) continue;
if(vis[x[i].v]) continue;
son++;
}
while(son!=){
int minn=inf,pos=-;
for(int i=head[f];i!=-;i=x[i].nex){
if((delu==f&&delv==x[i].v)||(delu==x[i].v&&delv==f)) continue;
if(x[i].v==fath) continue;
if(vis[x[i].v]) continue;
if(x[i].v<minn){
minn=x[i].v;
pos=x[i].v;
}
}
if(pos==-) break;
vis[pos]=;
st[++st[]]=pos;
if(st[st[]]>da[st[]]&&pig!=){pig=;return;}
if(st[st[]]<da[st[]]){pig=;}
dfs(pos,f);
son--;
}
return;
}
struct node1{
int u,v;
}se[];
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
memset(da,,sizeof(da));
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++){
int u=read(),v=read();
add(u,v),add(v,u);
se[i].u=u,se[i].v=v;
}
delu=-,delv=-;
if(m==n-){
st[]=;
st[st[]]=;
dfs(,);
for(int i=;i<=st[];i++) cout<<st[i]<<" ";
return ;
}
else{
for(int i=;i<=m;i++){
pig=;
memset(vis,,sizeof(vis));
delu=se[i].u,delv=se[i].v;
st[]=;
st[]=;
vis[]=;
dfs(,);
if(st[]!=n) continue;
bool ff=;
for(int j=;j<=n;j++){
if(st[j]>da[j]){ff=;break;}
if(st[j]<da[j]){ff=;break;}
}
if(ff){
for(int j=;j<=n;j++) da[j]=st[j];
}
}
for(int j=;j<=n;j++) cout<<da[j]<<" ";
cout<<endl;
return ;
}
}

考场代码

$update\space at\space 20190926$

突然想写一发 $O(n\log n)$ 的做法。

考虑如何对于基环树不删边求解,对于基环树可以对基环树的一个点暂时不走然后在通过另一侧的环经过。

然后记一下若能返悔最优的点即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<climits>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int MAXN=;
struct node{
int u,v,nex;
}x[MAXN<<];
int head[MAXN],vis[MAXN],cnt,n,m,INF=INT_MAX;
void add(int u,int v){
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
vector<int> vec;
namespace Tree{
void dfs(int u,int fath){
priority_queue<int> que;vec.push_back(u);
for(int i=head[u];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
que.push(-x[i].v);
}while(!que.empty()){
int xx=-que.top();que.pop();
dfs(xx,u);
} return;
}
void Solve(){
dfs(,);
for(int i=;i<vec.size();i++) printf("%d ",vec[i]);printf("\n");exit();
}
}
namespace RingTree{
int cir[MAXN],vis[MAXN];
bool flag;
void dfs1(int u,int fath){
vis[u]=;
for(int i=head[u];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
if(vis[x[i].v]) {cir[x[i].v]=cir[u]=;flag=;return;}
dfs1(x[i].v,u);
if(cir[x[i].v]&&flag){if(cir[u]) flag=;cir[u]=;return;}
}return;
}
void dfs2(int u,int fath,int res){
if(vis[u]) return;
vis[u]=;vec.push_back(u);
priority_queue<int> que;
for(int i=head[u];i!=-;i=x[i].nex){
if(x[i].v==fath||vis[x[i].v]) continue;
que.push(-x[i].v);
}
while(!que.empty()){
int xx=-que.top();que.pop();
if(que.empty()&&cir[xx]&&flag&&xx>res){flag=;return;}
if(!que.empty()&&cir[u]) dfs2(xx,u,-que.top());
else dfs2(xx,u,res);
}return;
}
void Solve(){
dfs1(,);memset(vis,,sizeof(vis));flag=;dfs2(,,INF);
for(int i=;i<vec.size();i++) printf("%d ",vec[i]);printf("\n");exit();
}
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++){int u=read(),v=read();add(u,v),add(v,u);}
if(m==n-) Tree::Solve();
if(m==n) RingTree::Solve();
}

$5.game$

$65$分找规律。

考场代码(附$dfs$)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
#define mod 1000000007
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int n,m,a[][],k,ans,cnt_dig[][],cnt_zimu[][],dig[],zimu[];
void dfs1(int x,int y){
if(x==n&&y==m){
cnt_dig[][]++;
for(int i=;i<=k;i++) cnt_dig[cnt_dig[][]][i]=dig[i],cnt_zimu[cnt_dig[][]][i]=zimu[i];
return;
}
if(x+<=n){
zimu[++k]=;
dig[k]=a[x+][y];
dfs1(x+,y);
k--;
}
if(y+<=m){
zimu[++k]=;
dig[k]=a[x][y+];
dfs1(x,y+);
k--;
}
return;
}
bool check(){
memset(dig,,sizeof(dig));
memset(zimu,,sizeof(zimu));
memset(cnt_dig,,sizeof(cnt_dig));
memset(cnt_zimu,,sizeof(cnt_zimu));
dfs1(,);
bool ff=;
for(int i=;i<=cnt_dig[][];i++){
for(int j=;j<=cnt_dig[][];j++){
if(i==j) continue;
int st=;
for(int p=;p<=n+m-;p++){
if(cnt_zimu[i][p]<cnt_zimu[j][p]){st=;break;}
if(cnt_zimu[i][p]>cnt_zimu[j][p]){st=;break;}
}
if(st==){
int sry=;
for(int p=;p<=n+m-;p++){
if(cnt_dig[i][p]>cnt_dig[j][p]){sry=;break;}
if(cnt_dig[i][p]<cnt_dig[j][p]){sry=;break;}
}
if(sry==)return ;
}
}
}
return ;
}
int tot;
void dfs(int h,int l){
if(h==n+){
if(check()) {
ans++;
ans%=mod;
}
return;
}
if(l!=m){
a[h][l]=;
dfs(h,l+);
a[h][l]=;
dfs(h,l+);
}
else{
a[h][l]=;
dfs(h+,);
a[h][l]=;
dfs(h+,);
}
}
int query(int x,int y){
if(x==){
if(y==) return ;
if(y==) return ;
if(y==) return ;
}
if(x==){
if(y==) return ;
if(y==) return ;
if(y==) return ;
}
if(x==){
if(y==) return ;
if(y==) return ;
if(y==) return ;
}
}
signed main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
n=read(),m=read();
if(n<=&&m<=){cout<<query(n,m);return ;}
if(n==){
int ans=;
for(int i=;i<=m;i++) ans*=,ans%=mod;
cout<<ans;
return ;
}
if(n==){
int ans=;
for(int i=;i<=m-;i++) ans*=,ans%=mod;
cout<<ans;
return ;
}
if(n==){
int ans=;
for(int i=;i<=m-;i++) ans*=,ans%=mod;
cout<<ans;
return ;
}
return ;
}

$6.defense$

$44$分的暴力

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,nex;
}x[];
int n,m,val[],cnt,head[];
void add(int u,int v){
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int tot,dp[][],px,bx,py,by,inf;
char str[];
void dfs(int f,int fath){
int son=;
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
son++;
}
if(son==){
if(f==px||f==py){
if(f==px){
if(bx==) dp[f][]=val[f],dp[f][]=inf;
if(bx==) dp[f][]=,dp[f][]=inf;
}
if(f==py){
if(by==) dp[f][]=val[f],dp[f][]=inf;
if(by==) dp[f][]=val[],dp[f][]=inf;
}
}
else{
dp[f][]=;
dp[f][]=val[f];
}
return;
}
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
dfs(x[i].v,f);
if(f==px||f==py){
if(f==px){
if(bx==){
dp[f][]+=min(dp[x[i].v][],dp[x[i].v][]);
if(min(dp[x[i].v][],dp[x[i].v][])==inf) dp[f][]=inf;
}
if(bx==){
dp[f][]+=dp[x[i].v][];
if(dp[x[i].v][]==inf) dp[f][]=inf;
}
}
if(f==py){
if(by==){
dp[f][]+=dp[x[i].v][];
if(dp[x[i].v][]==inf) dp[f][]=inf;
}
if(by==){
dp[f][]+=min(dp[x[i].v][],dp[x[i].v][]);
if(min(dp[x[i].v][],dp[x[i].v][])==inf) dp[f][]=inf;
}
}
}
else{
dp[f][]+=dp[x[i].v][];
dp[f][]+=min(dp[x[i].v][],dp[x[i].v][]);
if(min(dp[x[i].v][],dp[x[i].v][])==inf) dp[f][]=inf;
if(dp[x[i].v][]==inf) dp[f][]=inf;
}
}
if(dp[f][]!=inf) dp[f][]+=val[f];
return;
}
signed main(){
// freopen("defense.in","r",stdin);
// freopen("defense.out","w",stdout);
inf=<<-;
memset(head,-,sizeof(head));
n=read(),m=read();
scanf("%s",str+); for(int i=;i<=n;i++) val[i]=read();
for(int i=;i<n;i++){
int u=read(),v=read();
add(u,v),add(v,u);
}
while(m--){
px=read(),bx=read(),py=read(),by=read();
memset(dp,,sizeof(dp));
dp[px][bx^]=inf,dp[py][by^]=inf;
dfs(,);
int k=min(dp[][],dp[][]);
if(k>=inf){cout<<-<<endl;continue;}
printf("%lld\n",k);
}
}

然后直接动态$dp$即可。

update:分数线出来了,提高$300$,普及$190$。

NOIP2018普及&提高题解的更多相关文章

  1. 『NOIP2018普及组题解』

    标题统计 题目描述 凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符? 注意:标题中可能包含大.小写英文字母.数字字符.空格和换行符.统计标题字 符数时,空格和换行符不计算在内. 输入格式 ...

  2. 【NOIP2018】提高组题解

    [NOIP2018]提高组题解 其实就是把写过的打个包而已 道路铺设 货币系统 赛道修建 旅行 咕咕咕 咕咕咕

  3. 【资源】NOIP2013测试数据senior/junior 普及/提高 数据

    https://yunpan.cn/cRSepfcG4XX3V  访问密码 48e1 NOIP2013测试数据senior/junior 普及/提高 数据都在了

  4. NOIP2008普及组题解

    NOIP2008普及组题解 从我在其他站的博客直接搬过来的 posted @ 2016-04-16 01:11 然后我又搬回博客园了233333 posted @ 2016-06-05 19:19 T ...

  5. NOIP2018普及初赛解析

    2018年第二十四届全国青少年信息学奥林匹克联赛初赛普及组真题解析 一.单项选择题 1. 以下哪一种设备属于输出设备:(D) A.扫描仪 _B.键盘C. 鼠标 _D. 打印机 解析:送分题,前三个都是 ...

  6. NOIP初赛知识点大全-普及+提高组

    NOIP初赛知识点大全-普及+提高组 https://mp.weixin.qq.com/s/vSXLDxmbBoFfZPzD8lrt3w

  7. NOIP2018普及组复赛游记

    2018年11月10日,NOIP2018普及组复赛. 这是我初中阶段最后一次复赛了. 和往常一样,我们在预定的早上7点,没有出发. 10分钟之后,人终于到齐了,于是出发了,一路无话. 到了南航,合照三 ...

  8. NOIP2018普及组初赛解题报告

    本蒟蒻参加了今年的NOIP2018普及组的初赛 感觉要凉 总而言之,今年的题要说完全没有难度倒也不至于,还有不少拼RP的题,比如第一次问题求解考逻辑推理,第一次完善程序考双链表等 下面我就和大家一起看 ...

  9. P5017 [NOIP2018 普及组] 摆渡车

    P5017 [NOIP2018 普及组] 摆渡车 题目 P5017 思路 将实际问题抽象后,不难发现这是一个 区间 \(DP\) 我们不妨认为时间是一条数轴,每名同学按照到达时刻分别对应数轴上可能重合 ...

随机推荐

  1. Mac环境下RabbitMq安装与测试教程

    RabbitMq安装与测试教程 Installing on Mac I. 安装 123456789 brew install rabbitmq ## 进入安装目录cd /usr/local/Cella ...

  2. Python文件操作大全

    Python 编程文件操作大全   文件打开模式 打开模式 执行操作 'r' 以只读方式打开文件(默认) 'w' 以写入的方式打开文件,会覆盖已存在的文件 'x' 如果文件已经存在,使用此模式打开将引 ...

  3. 单元测试模块unittest使用学习

    工作原理: unittest中最核心的四个概念是:test case, test suite, test runner, test fixture. 一个TestCase的实例就是一个测试用例.什么是 ...

  4. Elasticsearch 评分score计算中的Boost 和 queryNorm

    本来没有这篇文章,在公司分享ES的时候遇到一个问题,使用boost的时候,怎么从评分score中知道boost的影响. 虽然我们从查询结果可以直观看到,boost起了应有的作用,但是在explain的 ...

  5. 三:QJM HDFS高可用

    本文介绍的是HDFS的一种HA方案.虽然有checkpoint node \backup node等,但是不能实现自动的failover. http://hadoop.apache.org/docs/ ...

  6. POJ 2653 Pick-up sticks(线段判交)

    Description Stan has n sticks of various length. He throws them one at a time on the floor in a rand ...

  7. Thunder团队第一周 - Scrum会议3

    Scrum会议3 小组名称:Thunder 项目名称:在线考试系统 Scrum Master:杨梓瑞 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李 ...

  8. ES6之 =>箭头函数

    原文,请点此链接http://www.cnblogs.com/allenxieyusheng/p/5784728.html 1. 第一个函数 ()=>1 解析:其实这是一个匿名函数直接执行 (f ...

  9. C# 反射与dynamic最佳组合

    在 C# 中反射技术应用广泛,至于什么是反射.........你如果不了解的话,请看下段说明,否则请跳过下段.广告一下:喜欢我文章的朋友请关注一下我的blog,这也有助于提高本人写作的动力. 反射:当 ...

  10. C# 开发者最经常犯的 8 个错误

    在和C#新手一起工作的时候,我注意到他们经常重复一些错误.这些错误,当你指出来的时候很容易理解.然而,如果一个开发者没有意识到这些错误,将会影响正在开发的软件的质量和效率,因此,我决定总结8个常见的错 ...