思维练了三道,然后又看了lca的课,为了学重构树先去刷了最小生成树的一些基础题
其实一开始就都错题目了,初始的那些温度也是可以被改变的,所以我们可以想一下如果左边的空调温度加上距离后比当前位置的空调温度还要低,那当前空调的温度就要更新,同理右边也是如此,所以可以分别从左从右遍历一遍求出t[i]的最小值就可以
Codeforces Round #731 (Div. 3) E. Air Conditioners (思维)_半碗无糖蓝莓冻的博客-CSDN博客
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll q,n,k,a[300005],t[300005];
- int main(){
- scanf("%lld",&q);
- while(q--){
- scanf("%lld%lld",&n,&k);
- for(int i=1;i<=k;i++) scanf("%lld",&a[i]);
- for(int i=0;i<=n+1;i++) t[i]=1e18;
- for(int i=1;i<=k;i++) scanf("%lld",&t[a[i]]);
- for(int i=1;i<=n;i++) t[i]=min(t[i],t[i-1]+1);
- for(int i=n;i>=1;i--) t[i]=min(t[i],t[i+1]+1);
- for(int i=1;i<=n;i++) printf("%lld ",t[i]);
- printf("\n");
- }
- system("pause");
- return 0;
- }
-
s=" "+s才可以,s=""+s是不可以的!!!
分清楚情况传递关系搞清楚就可以,难的是在实现上
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll t,n;
- bool dp[3][200005][7];
- string s[3];
- int main(){
- scanf("%lld",&t);
- while(t--){
- scanf("%lld",&n);
- cin>>s[1]>>s[2];s[2]=" "+s[2];s[1]=" "+s[1];
- for(int i=0;i<=n+1;i++)
- for(int j=0;j<=6;j++) dp[0][i][j]=dp[1][i][j]=dp[2][i][j]=0;
- for(int p=1;p<=2;p++){
- for(int j=1;j<=n;j++){
- for(int i=1;i<=2;i++){
- if(s[i][j]=='1'||s[i][j]=='2'){
- s[i][j]='1';
- if(i==1&&j==1){dp[i][j][2]=1;}
- if(i==1&&s[i][j+1]>'2') dp[i][j+1][4]=dp[i][j][2];
- else if(s[i][j+1]>'2') dp[i][j+1][5]=dp[i][j][2];
- if(s[i][j+1]<'3') dp[i][j+1][2]=dp[i][j][2];
- }
- else{
- s[i][j]='3';
- if(i==1&&j==1){dp[i][j][4]=1;}
- if(i==1){
- dp[i][j][3]=dp[i+1][j][5];
- if(s[i][j+1]>'2') dp[i][j+1][4]=dp[i][j][3];
- if(s[i][j+1]<'3') dp[i][j+1][2]=dp[i][j][3];
- }
- else{
- dp[i][j][6]=dp[i-1][j][4];
- if(s[i][j+1]<'3') dp[i][j+1][2]=dp[i][j][6];
- if(s[i][j+1]>'2') dp[i][j+1][5]=dp[i][j][6];
- }
- }
- }
- }
- }
- // cout<
- if(dp[2][n][2]&&s[2][n]=='1'||dp[2][n][6]&&s[2][n]=='3') printf("YES\n");
- else printf("NO\n");
- }
- system("pause");
- return 0;
- }
-
dp[i][j][0]表示走到了第j个位置,往左走了i步,这次是往右走所能获得的最大价值,dp[i][j][1]就是往左走能获得的最大价值,一共走了多少步也很容易能算出来即j-1+2*i,然后根据题目来列方程就可以,要注意第一层循环要循环z,不然dp[i-1][j+1][0]可能会没有更新
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll t,n,k,z,a[100005],dp[6][100005][2];
- int main(){
- scanf("%lld",&t);
- while(t--){
- scanf("%lld%lld%lld",&n,&k,&z);
- for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
- for(int i=0;i<=5;i++)
- for(int j=0;j<=n;j++) dp[i][j][0]=dp[i][j][1]=0;
- ll ans=0;
- for(int i=0;i<=z;i++){
- for(int j=1;j<=n;j++){
- if(i==0&&j==1){
- dp[0][j][0]=a[j];continue;
- }
- if(j-1+2*i<=k){
- if(i>0) dp[i][j][1]=max(dp[i][j][1],dp[i-1][j+1][0]+a[j]);
- dp[i][j][0]=max({dp[i][j][0],dp[i][j-1][0]+a[j],dp[i][j-1][1]+a[j]});
- }
- else break;
- ans=max({ans,dp[i][j][0],dp[i][j][1]});
- }
- }
- printf("%lld\n", ans);
- }
- system("pause");
- return 0;
- }
-
lca树剖做法的模板
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll n,m,s,siz[500005],d[500005],son[500005],f[500005],top[500005];
- ll cnt,head[500005];
- struct Edge{
- ll from,to,next;
- }edge[10000006];
- void addedge(ll from, ll to){
- edge[++cnt].from = from;
- edge[cnt].to = to;
- edge[cnt].next =head[from];
- head[from] = cnt;
- }
- void dfs1(ll x,ll fa){
- siz[x]=1;d[x]=d[fa]+1;
- son[x]=0;f[x]=fa;
- for(int i=head[x];i;i=edge[i].next){
- ll j=edge[i].to;
- if(j==fa) continue;
- dfs1(j,x);
- siz[x]+=siz[j];
- if(siz[son[x]]
- }
- }
- void dfs2(ll x,ll topx){
- top[x]=topx;
- if(son[x]) dfs2(son[x],topx);
- for(int i=head[x];i;i=edge[i].next){
- if(edge[i].to!=f[x]&&edge[i].to!=son[x])
- dfs2(edge[i].to,edge[i].to);
- }
- }
- ll lca(ll x,ll y){
- while(top[x]!=top[y]){
- if(d[top[x]]
- swap(x,y);
- x=f[top[x]];
- }
- return d[x]
- }
- int main(){
- scanf("%lld%lld%lld",&n,&m,&s);
- for(int i=1;i
- ll u,v;
- scanf("%lld%lld",&u,&v);
- addedge(u,v);
- addedge(v,u);
- }
- dfs1(s,0);
- dfs2(s,s);
- while(m--){
- ll u,v;
- scanf("%lld%lld",&u,&v);
- printf("%lld\n",lca(u,v));
- }
- system("pause");
- return 0;
- }
-
P1194 买礼物 - 最小生成树模板
这个也算是最小生成树的模板了,需要注意的是优惠可能比原价还贵,,,
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll n,m,s[500005],cost[500005];
- ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
- struct node{
- ll u,v,w;
- bool operator<(const node& a)const{
- return w
- }
- }edge[500005];
- ll kruskal(){
- ll ans=0;
- for(int i=1;i<=m;i++) s[i]=i;
- sort(edge+1,edge+m*m+1);
- ll cnt=0;
- for(int i=1;i<=m*m;i++){
- ll x=findd(edge[i].u);
- ll y=findd(edge[i].v);
- if(x==y) continue;
- s[x]=y;
- ans+=edge[i].w;
- cnt++;
- if(cnt>=m-1) break;
- }
- return ans;
- }
- int main(){
- scanf("%lld%lld",&n,&m);
- for(int i=1;i<=m;i++)
- for(int j=1;j<=m;j++){
- ll x;
- scanf("%lld",&x);
- edge[(i-1)*m+j].w=x==0?n:min(x,n);
- edge[(i-1)*m+j].u=i;
- edge[(i-1)*m+j].v=j;
- }
- printf("%lld\n",kruskal()+n);
- system("pause");
- return 0;
- }
-
P1195 口袋的天空 - 最小生成树
一直没看懂题意,最后还是在讨论区里知道的题意,要把n个点连成k个连通分量,也就是要剩下k个分量,剩下一个分量时需要n-1条边,剩下k个分量时就是需要n-k条边,需要注意的就是这一点
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll n,m,k,s[1005],vis[1005];
- ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
- struct node{
- ll x,y,w;
- bool operator<(const node& a)const{
- return w
- }
- }ed[10005];
- ll kruscal(){
- ll ans=0,cnt=0,flag=0;
- for(int i=1;i<=n;i++) s[i]=i,vis[i]=0;
- sort(ed+1,ed+m+1);
- for(int i=1;i<=m;i++){
- ll x=findd(ed[i].x),y=findd(ed[i].y);
- if(x==y) continue;
- s[x]=y;
- cnt++;
- ans+=ed[i].w;
- if(cnt>=n-k){flag=1;break;}
- }
- if(!flag) return -1;
- return ans;
- }
- int main(){
- scanf("%lld%lld%lld",&n,&m,&k);
- for(int i=1;i<=m;i++){
- scanf("%lld%lld%lld",&ed[i].x,&ed[i].y,&ed[i].w);
- }
- ll ans=kruscal();
- if(ans==-1) printf("No Answer");
- else printf("%lld\n",ans);
- system("pause");
- return 0;
- }
-
P1536 村村通 - 并查集
有连通分量的思想,用并查集合并能合并的点,最后看看还剩下几个连通分量,答案就是剩下的连通分量个数-1;
- #include
- #define ll long long
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- ll n,m,s[1005],vis[1005];
- ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
- void uni(ll x,ll y){
- ll xx=findd(x),yy=findd(y);
- if(xx!=yy){
- s[xx]=yy;
- }
- }
- int main(){
- while(scanf("%lld", &n)!=EOF){
- if(n==0) break;
- scanf("%lld", &m);
- for(int i=1;i<=n;i++) s[i]=i,vis[i]=0;
- for(int i=1;i<=m;i++){
- ll u,v;
- scanf("%lld%lld", &u, &v);
- uni(u,v);
- }
- ll ans=0;
- for(int i=1;i<=n;i++){
- if(!vis[findd(i)]) vis[findd(i)]=1,ans++;
- }
- printf("%lld\n",ans-1);
- }
- system("pause");
- return 0;
- }
-
-
相关阅读:
【HCSD大咖直播】亲授大厂面试秘诀【云驻共创】
Windows安装docker
Redis-02
运算符与表达式
Python入门指南:探索无限可能的编程世界
java 单元测试Junit
pytorch中gather函数详解【包你看懂,我敢说在CSDN上没人解释的比我清楚】
@vue/cli创建项目遇到ERROR Failed to get response from /vue-cli-version-marker 解决方法
Mysql允许远程访问
Vatee万腾的数字化掌舵:Vatee科技引领未来的新高度
-
原文地址:https://blog.csdn.net/weixin_52621204/article/details/125886730