没啥可说的,暴力大赛
水题,贪心的尽量向右构造即可
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 505;
int n,p[N],ans[N][N];
void T()
{for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cout<<ans[i][j]<<" ";}cout<<endl;}
}
int main()
{speed();freopen("in.in","r",stdin);freopen("out.out","w",stdout);cin>>n;for(int i=1;i<=n;i++)cin>>p[i];for(int i=1;i<=n;i++){ans[i][i]=p[i];}for(int i=1;i<=n;i++){int num=p[i],cnt=p[i]-1;int x=i,y=i;while(cnt){// cout<<x<<" "<<y<<endl;if(x<=n&&y<=n){if(y-1>0&&!ans[x][y-1]){y=y-1;ans[x][y]=num;cnt--;}else if(x+1<=n&&!ans[x+1][y]){ ans[x+1][y]=num;x++;cnt--;}}}}for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cout<<ans[i][j]<<" ";}cout<<endl;}return 0;
}
/*
4
3 4 2 1
*/
这题,数据过水,考虑暴力,把\(1\)的所有儿子之间互相讨论,每个儿子之间跑最短路.76分,注意最短路每个儿子跑一遍就行,但是要用\(vector\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 4e4+5;
int n,head[N],cnt,m,fa[N];
struct ed
{int to,next,w;
}edge[N*2];
struct node{int u,v,w,id;};inline void add(int u,int v,int w)
{edge[++cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;// cout<<u<<"->"<<v<<" "<<cnt<<endl;
}
bool vis[N*2];
struct AC
{int u,w;bool operator < (const AC& a)const{return w>a.w;}
};
vector <int> dis[N];
inline void dij(int st,int ed)
{dis[st].resize(n+1,1e9);bool VIS[N]={};priority_queue <AC> q;q.push({st,0});dis[st][st]=0;while(q.size()){int u=q.top().u;q.pop();if(VIS[u])continue;VIS[u]=1;for(int i=head[u];i;i=edge[i].next){int to=edge[i].to;if(VIS[to]||vis[i]||to==1)continue;if(dis[st][to]>dis[st][u]+edge[i].w){dis[st][to]=dis[st][u]+edge[i].w;q.push({to,dis[st][to]});}}}return ;
}
int main()
{speed();// freopen("leave.in","r",stdin);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);int T;cin>>T;while(T--){cin>>n>>m;int u,v,d;cnt=1;// cout<<n<<" "<<m<<endl;for(int i=1;i<=n;i++)head[i]=0,dis[i].clear();for(int i=1;i<=m;i++){cin>>u>>v>>d;vis[i]=vis[i+m]&=0;add(u,v,d);add(v,u,d);}vis[2*m+1]=0;// kruskal();dis[1]=0;// dfs(1);int ans=1e9;// cout<<"******"<<endl;vector <pii> p;for(int i=head[1];i;i=edge[i].next){vis[i]=1;vis[i^1]=1;// cout<<i<<endl;int to=edge[i].to;p.pb({to,edge[i].w});}ll ans=1e18;for(register int i=0;i<p.size();i=-~i){int u=p[i].first;dij(u,0);for(register int j=i+1;j<p.size();j=-~j){int v=p[j].first;if(dis[u][v]==1e9)continue;// cout<<val<<endl;ans=min<ll>(ans,p[i].second+p[j].second+dis[u][v]);}}// for(int i=0;i<m;i++)// {// if(vis[e[i].id])continue;// int lc=lca(e[i].u,e[i].v);// if(lc==1)// {// ans=min(ans,dis[e[i].u]+dis[e[i].v]+e[i].w);// }// }if(ans==1e18)cout<<-1<<endl;elsecout<<ans<<endl;}return 0;
}
/*
4
3 4 2 1
*/
考场上假的思路,感觉写的很好,可惜了(出题人数据范围给错了),为什么是错的:\(Kruskal\)找的树根到一个点的距离不一定是最近的(贪败了)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e5+5;
int n,head[N],cnt,m,fa[N],dis[N],f[N][25],dep[N];
struct ed
{int to,next,w;
}edge[N*2];
struct node{int u,v,w,id;};
vector <node> e;
vector <pii> eg[N];
void add(int u,int v,int w)
{edge[++cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;// cout<<u<<"->"<<v<<" "<<cnt<<endl;
}
inline int find(int x){if(fa[x]!=x)fa[x]=find(fa[x]);return fa[x];
}
bool cmp(node a,node b)
{return a.w<b.w;
}
bool vis[N*2];
int lca(int u,int v)
{if(dep[u]<dep[v])swap(u,v);for(int i=20;i>=0;i--)if(dep[f[u][i]]>=dep[v])u=f[u][i];if(u==v)return u;for(int i=20;i>=0;i--)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];return f[u][0];
}
void dfs(int u)
{// cout<<u<<endl;for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];dep[u]=dep[f[u][0]]+1;for(auto [to,w]:eg[u]){if(to==f[u][0])continue;dis[to]=dis[u]+w;f[to][0]=u;dfs(to);}}
void kruskal()
{for(int i=1;i<=n;i++)fa[i]=i;sort(e.begin(),e.end(),cmp);for(int i=0;i<m;i++){// cout<<i<<endl;int fu=find(e[i].u),fv=find(e[i].v);if(fu!=fv){fa[fv]=fu;vis[e[i].id]=1;eg[e[i].u].pb({e[i].v,e[i].w});eg[e[i].v].pb({e[i].u,e[i].w});}}
}
int main()
{speed();freopen("leave.in","r",stdin);// freopen("in.in","r",stdin);freopen("out.out","w",stdout);int T;cin>>T;while(T--){cin>>n>>m;int u,v,d;// cout<<n<<" "<<m<<endl;memset(vis,0,sizeof vis);memset(f,0,sizeof f);memset(dep,0,sizeof dep);memset(dis,0,sizeof dis); for(int i=1;i<=n;i++)head[i]=0,dis[i]=0,eg[i].clear();e.clear();for(int i=1;i<=m;i++){cin>>u>>v>>d;e.pb({u,v,d,i});}kruskal();dis[1]=0;dfs(1);int ans=1e9;// cout<<"******"<<endl;for(int i=0;i<m;i++){if(vis[e[i].id])continue;int lc=lca(e[i].u,e[i].v);if(lc==1){ans=min(ans,dis[e[i].u]+dis[e[i].v]+e[i].w);}}if(ans==1e9)cout<<-1<<endl;elsecout<<ans<<endl;}return 0;
}
/*
4
3 4 2 1
*/
其实,加了是因为不是最短路的问题,我们只需要把他改为最短路树即可,特别感谢\(CuFeO4\)
参考CuFeO4代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#ifdef LOCALFILE *InFile = infile("in.in"),*OutFile = outfile("out.out");// FILE *ErrFile=errfile("err.err");
#elseFILE *Infile = stdin,*OutFile = stdout;//FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 1e4 + 10;
struct EDGE{int to,next,w;}edge[N<<4];
int head[N],cnt;
inline void add(int u,int v,int w){edge[++cnt] = {v,head[u],w};head[u] = cnt;
}
int n,m;
vector<int> son[N];
bitset<N> vis;
int dist[N],fa[N];
inline void dijkstra(int s){vis.reset();for(int i = 1;i <= n; ++i)dist[i] = 0x3f3f3f3f;__gnu_pbds::priority_queue<pair<int,int>,greater<pair<int,int> > > q;dist[s] = 0;q.push(make_pair(dist[s],s));while(q.size()){int x = q.top().second;q.pop();if(vis[x]) continue;vis[x] = true;for(int i = head[x]; i;i = edge[i].next){int y = edge[i].to;if(dist[y] > dist[x] + edge[i].w){dist[y] = dist[x] + edge[i].w;q.push(make_pair(dist[y],y));fa[y] = x;} }}
}
int belong[N];
void dfs(int x,int z){belong[x] = z;for(auto i : son[x]) dfs(i,z);
}
inline void solve(){int T;cin>>T;memset(dist,0x3f,sizeof dist);while(T--){cin>>n>>m;for(int i = 1,u,v,w;i <= m; ++i){cin>>u>>v>>w;add(u,v,w);add(v,u,w);}dijkstra(1);for(int i = 2;i <= n; ++i) son[fa[i]].emplace_back(i);int ans = 0x3f3f3f3f;for(auto i : son[1]) dfs(i,i);belong[1] = 1;for(int x = 2;x <= n; ++x){for(int i = head[x]; i;i = edge[i].next){int y = edge[i].to;if(belong[x] == belong[y] || !belong[x] || !belong[y] || fa[x] == y) continue;ans = min(ans,dist[x] + dist[y] + edge[i].w);}}cout<<(ans == 0x3f3f3f3f?-1:ans)<<'\n';for(int i = 1;i <= n; ++i) head[i] = 0;for(int i = 1;i <= n; ++i) belong[i] = fa[i] = 0;for(int i = 1;i <= n; ++i) vector<int> ().swap(son[i]);cnt = 0;}}
signed main(){cin.tie(nullptr)->sync_with_stdio(false);cout.tie(nullptr)->sync_with_stdio(false);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);solve();
}
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e5+5;
int n,m,dis[N],head[N];
struct node{int u,v,w,id;};
vector <node> e;
vector <int> E[N];
struct ed
{int to,next,w;
}edge[N*2];int cnt;
bool cmp(node a,node b)
{return a.w<b.w;
}
bool vis[N*2];
inline void add(int u,int v,int w)
{edge[++cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;// cout<<u<<"->"<<v<<" "<<cnt<<endl;
}
int pre[N],belong[N];
struct AC
{int u,w;bool operator < (const AC& a)const{return w>a.w;}
};
bool VIS[N];
inline void dij(int st)
{for(int i=1;i<=n;i++)dis[i]=1e9,VIS[i]=0;priority_queue <AC> q;q.push({st,0});dis[st]=0;while(q.size()){int u=q.top().u;q.pop();if(VIS[u])continue;VIS[u]=1;// cout<<u<<endl;for(int i=head[u];i;i=edge[i].next){int to=edge[i].to;// cout<<to<<endl;if(VIS[to])continue;if(dis[to]>dis[u]+edge[i].w){dis[to]=dis[u]+edge[i].w;pre[to]=u;q.push({to,dis[to]});}}}return ;
}
void dfs(int u,int ans)
{belong[u]=ans;for(auto to:E[u]){dfs(to,ans);}
}
int main()
{speed();// freopen("leave.in","r",stdin);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);int T;cin>>T;while(T--){for(int i=1;i<=n;i++)head[i]=0,belong[i]=0,E[i].clear(),pre[i]=0;cin>>n>>m;int u,v,d;cnt=0;for(int i=1;i<=m;i++){cin>>u>>v>>d;add(u,v,d);add(v,u,d);}dij(1);for(int i=2;i<=n;i++)E[pre[i]].pb(i);for(auto to:E[1]){dfs(to,to);}belong[1]=1;int ans=1e9;for(int x = 2;x <= n; ++x){for(int i = head[x]; i;i = edge[i].next){int y = edge[i].to;if(belong[x] == belong[y] || !belong[x] || !belong[y] ||pre[x] == y) continue;ans = min(ans,dis[x] + dis[y] + edge[i].w);}}cout<<(ans==1e9?-1:ans)<<endl;}return 0;
}
/*
4
3 4 2 1
*/
T4
考场上写的状压,没想到\(n^22^n\)的搜居然能得\(60\)分,逆天
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 2e5+5;
int n,a[N];
inline bool dfs(int l,int r,int mx,int mi)
{if(l>r)return 1;ll ans=0;if(a[l]>mx)ans|=dfs(l+1,r,a[l],mi);if(ans)return ans;if(a[l]<mi)ans|=dfs(l+1,r,mx,a[l]);return ans;
}
int main()
{speed();// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);cin>>n;for(int i=1;i<=n;i++)cin>>a[i];ll ans=0;for(int i=1;i<=n;i++){for(int j=i;j<=n;j++){if(j-i+1<=3)ans++;else{if(dfs(i,j,-1e9,1e9)){ans++;}// ans+=(dfs(i,j,0,a[i])||dfs(i,j,a[i],0));}}}cout<<ans<<endl;return 0;
}
更逆天的是\(O(nlogn2^n)\)居然过了,其实造一组单调递减的序列就卡点了
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 2e5+5;
int n,a[N];
inline bool dfs(int l,int r,int mx,int mi)
{if(l>r)return 1;ll ans=0;if(a[l]>mx)ans|=dfs(l+1,r,a[l],mi);if(ans)return ans;if(a[l]<mi)ans|=dfs(l+1,r,mx,a[l]);return ans;
}inline int fen(int l,int r)
{int L=l,R=r;int ans=l;while(L<=R){int mid=(L+R)>>1;if(dfs(l,mid,-1e9,1e9))L=mid+1,ans=mid;else R=mid-1;}return ans;
}
int main()
{speed();// freopen("count.in","r",stdin);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);cin>>n;for(int i=1;i<=n;i++)cin>>a[i];ll ans=0;for(int i=1;i<=n;i++){int r=fen(i,n);ans+=r-i+1;}cout<<ans;return 0;
}
胡扯结束,现在是正解:
我们发现影响结果的只有递增序列最后一个值与递减序列最后一个值,我们设\(dp_{i,0}\)表示递增序列中递减序列最后一个元素最大值,递减序列中递增序列最后一个元素最小值
我们现在可以\(O(n)\)检查区间的合法性了
还可以优化,固定\(l\)然后枚举\(r\),是具有单调性的,这是\(O(n^2)\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 2e5+5,inf=1e9;
int n,a[N],dp[N][2];
inline int check(int l)
{for(int i=l;i<=n;i++)dp[i][0]=-inf,dp[i][1]=inf;dp[l][0]=inf;dp[l][1]=-inf;int res=1;for(int i=l;i<=n;i=-~i){if(dp[i-1][0]!=-inf){if(a[i]>a[i-1])dp[i][0]=max(dp[i][0],dp[i-1][0]);if(a[i]<dp[i-1][0])dp[i][1]=min(dp[i][1],a[i-1]);}if(dp[i-1][1]!=inf){if(a[i]<a[i-1])dp[i][1]=min(dp[i][1],dp[i-1][1]);if(a[i]>dp[i-1][1])dp[i][0]=max(dp[i][0],a[i-1]);}// cout<<res<<endl;if(i!=l&&(dp[i][0]!=-inf||dp[i][1]!=inf))res++;else if(i!=l)return res;}// cout<<res<<endl;return res;
}
int main()
{speed();// freopen("count.in","r",stdin);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);cin>>n;for(int i=1;i<=n;i++)cin>>a[i];ll ans=0;for(int i=1;i<=n;i++){ans+=check(i);}cout<<ans;return 0;
}
如何做到现行的呢,倒着枚举
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 2e5+5,inf=1e9;
int n,a[N],dp[N][2];ll ans=0,last;
void check(int l)
{dp[l][0]=inf;dp[l][1]=-inf;for(int i=l+1;i<=n;i++){int w0=-inf,w1=inf;if(dp[i-1][0]!=-inf){if(a[i]>a[i-1])w0=max(w0,dp[i-1][0]);if(a[i]<dp[i-1][0])w1=min(w1,a[i-1]);}if(dp[i-1][1]!=inf){if(a[i]<a[i-1])w1=min(w1,dp[i-1][1]);if(a[i]>dp[i-1][1])w0=max(w0,a[i-1]);}if(dp[i][1]==w1&&dp[i][0]==w0)break;else dp[i][1]=w1,dp[i][0]=w0;if(dp[i][0]==-inf&&dp[i][1]==inf){last=i-1;break;}}ans+=last-l+1;
}
int main()
{speed();// freopen("count.in","r",stdin);// freopen("in.in","r",stdin);// freopen("out.out","w",stdout);cin>>n;for(int i=1;i<=n;i++)cin>>a[i];last=n;for(int i=n;i>=1;i--){check(i);}cout<<ans;return 0;
}