0%

思路讲解

非常暴力的模拟,唯一记忆的地方就在于这个划线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
FOR(i,1,N){
if(ans[i][1]!=0){
cout<<ans[i][1]<<"\n";
continue;
}
ll cur=i,id=1;
vector<arr2> wp;
while(true){
wp.pb({cur,id});
ll v=g[cur][id];
FOR(i,1,num[v]){
if(g[v][i]==cur){
id=i;
}
}
if(id+1<=num[v]){
id+=1;
}else{
id=1;
}
if(ans[v][id]){
ll lans=ans[v][id]+SZ(st);
if(ans[v][id]==-1) lans=SZ(st);
for(auto &[x,idx]:wp){
ans[x][idx]=lans;
}
break;
}
ans[v][id]=-1;
arr2 t={cur,v};sort(all(t));
st.insert(t);
cur=v;
}
cout<<ans[i][1]<<"\n";
st.clear();
}

AC代码

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78205559

心路历程(WA,TLE,MLE……)

思路讲解

这个的状态定义比较巧妙,定义的是a1和aN/2的差,a1+a2与aN/2+1+aN/2+2的差

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FOR(i,1,N/2){
FOR(d,-(N-1),N-1){
FOR(j,0,N/2*N/2){
if(j+d<0) continue;
if(d<=0){
dp[i][j]+=dp[i-1][j+d]*ct_[i][abs(d)];
dp[i][j]%=mod;
}else{
dp[i][j]+=dp[i-1][j+d]*ct[i][d];
dp[i][j]%=mod;
}

}
}
}

AC代码

https://www.codechef.com/viewsolution/1172894021

心路历程(WA,TLE,MLE……)

思路讲解

AC代码

心路历程(WA,TLE,MLE……)

思路讲解

那么根据我的经验来说,如果说这个东西要求连续性(如距离,字母排列等等),大概率是树上dp,像这种具有超距作用的,那么大概率就是要配合DSU了。

核心代码如下,注意,先计算,后合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
FOR(i,1,N){		// 特判两个点的情况
for(auto &v:g[i]){
if(A[v]==A[i]) ++ans;
}
}
// 生成的这张图相当于其权值都是大于等于key的(至少是相连的图,孤立点我们不知道)
// 这个时候就是要看两个相同的A值点,是不是连接于这个图上面。
// 那么我们发现不用把问题想的非常复杂,只需要考虑key-1(即后面一个k)就行了
// 最重要的是遵循"先计数,后合并"的原则
for(auto it=mp.rbegin();it!=mp.rend();it++){
// auto& 相当于定义了一个别名
auto& ls=it->second;ll key=it->first;
map<ll,ll> cnt;
// 先计数
for(auto &u:ls){
vector<ll> wp;
for(auto &v:g[u]){
if(A[v]<=key) continue;
wp.pb(find(v));
}
wp.resize(unique(all(wp))-wp.begin());
for(auto &v:wp){
++cnt[find(v)];
}
}
for(auto &t:cnt){
ll n=t.second;
ans+=(n-1+1)*(n-1); // 2Cn * 2 在n个中选两个,然后由于先选哪个比较重要*2
}
// 后合并
for(auto &u:ls){
for(auto &v:g[u]){
if(A[v]<key) continue;
merge(u,v);
}
}
}

那么这种复杂路径问题,点分治也能解决(应该来说更泛用)。

AC代码

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78161052

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78175127

心路历程(WA,TLE,MLE……)

WA了的点分治代码,过了60%,我认为错误就在这个我的这个点分治统计答案他有点问题,统计到的不一定都经过u,这是违背点分治思想的。

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78164958

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78165041

然后改了统计代码以后WA的更多了

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78165092

AI指出了一个不对的地方,现在正确率提升到了84%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 保证计入答案的路径是经过u点的
for(auto &v:g[u]){
if(vis[v]) continue; // 你不能就不判断了
dfs(dfs,v,u,A[u]);
for(auto &a:wp){
if(cnt.count(a)){
ans+=cnt[a];
}
}
for(auto &a:wp){
++cnt[a];
}
wp.clear();
}

思路讲解

差分做法,只要用差分把所有坏区间都标记出来,剩下的就是不可行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FOR(i,0,M-2){
for(auto &p:pos[i+1]){
auto it=lower_bound(all(pos[i]),p);
if(it==pos[i].begin()){
diff[1]+=1;
// p+1是可行的(至少从这个p看来)
diff[p+1]-=1;
}else{
it--;ll idx=*it;
diff[idx+1]+=1;
// p+1是可行的(至少从这个p看来)
diff[p+1]-=1;
}
}
}

AC代码

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78135312

心路历程(WA,TLE,MLE……)