A割韭菜--线段树

题目链接:

A-割韭菜_哈尔滨理工大学第12届程序设计竞赛(同步赛) (nowcoder.com)

#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int N=1e5+10;
int t,n,m;
int a[N];
typedef struct Node{int l,r;ll maxh,minh;//区间里面韭菜的最大和最小高度ll maxv,minv;ll day;//上次收割日期 ll lz,ld;//懒标记,分别是区间高度和区间上次收割日期,-1表示无需下传 ll sum;//区间总韭菜长度 ll v;//区间韭菜的生长速度和
}Node;
Node tr[N*4];
void init_node(int u){tr[u].lz=-1,tr[u].day=0;tr[u].maxh=0,tr[u].minh=0;tr[u].sum=0;
}
void pushup1(int u){tr[u].v=tr[u<<1].v+tr[u<<1|1].v; tr[u].maxv=max(tr[u<<1].maxv,tr[u<<1|1].maxv);tr[u].minv=min(tr[u<<1].minv,tr[u<<1|1].minv);
}
void pushup2(int u){tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;tr[u].maxh=max(tr[u<<1].maxh,tr[u<<1|1].maxh);tr[u].minh=min(tr[u<<1].minh,tr[u<<1|1].minh);
}
void build(int u,int l,int r){tr[u].l=l,tr[u].r=r;init_node(u);if(l==r){tr[u].v=tr[u].minv=tr[u].maxv=a[l];return ;}int mid=(l+r)>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup1(u);
}
void lazy_union(int fa,int u){ll day=tr[fa].ld,h=tr[fa].lz;tr[u].ld=tr[u].day=day;tr[u].lz=tr[u].maxh=tr[u].minh=h;tr[u].sum=(tr[u].r-tr[u].l+1)*h;
}
void pushdown(int u){if(tr[u].lz!=-1){lazy_union(u,u<<1);lazy_union(u,u<<1|1);tr[u].lz=-1;}
}
ll query(int u,ll day,ll h){tr[u].maxh+=(day-tr[u].day)*tr[u].maxv;   tr[u].minh+=(day-tr[u].day)*tr[u].minv;tr[u].sum+=(day-tr[u].day)*tr[u].v;tr[u].day=day;ll res=0;if(tr[u].maxh<=h){return 0;}if(tr[u].minh>=h){res=tr[u].sum-(tr[u].r-tr[u].l+1)*h;tr[u].sum=(tr[u].r-tr[u].l+1)*h;tr[u].lz=h;tr[u].ld=day;tr[u].maxh=tr[u].minh=h;return res;}pushdown(u);int mid=(tr[u].l+tr[u].r)>>1;res+=query(u<<1,day,h);res+=query(u<<1|1,day,h);pushup2(u);return res;
}
int main(){scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}sort(a+1,a+n+1);build(1,1,n);ll d,b;while(m--){scanf("%lld%lld",&d,&b);printf("%lld\n",query(1,d,b));}}
}

D gk的爬山之旅--单调栈

题目链接:

D-gk的爬山之旅_哈尔滨理工大学第12届程序设计竞赛(同步赛) (nowcoder.com)

思路:

可以确定的是从i点开始,最高点我们用j表示,经过最长路径i->k1->k2->...->j获得的绝对值之和是最大的,因为当k1,k2,k3的位置满足k1<k2<k3时,因为g(x)是单增的。

但若是k1,k2,k3的位置满足k2<k1<k3时,

我们只需要用两个单调栈分别维护出对当前点u而言向左走或向右走第一个能到达点的位置。然后dp[u]=max(abs(g[u]-g[L[u]])+dp[L[u]],abs(g[u]-g[R[u]])+dp[R[u]]),可用dfs逐层求出dp[u]。

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;
const int N=1e6+10;
int L[N],R[N],idx[N];
int t,n;
int h[N],g[N];
ll dp[N];
int st[N],top;
bool book[N];
void init(){for(int i=1;i<=n;i++){dp[i]=0;book[i]=false;}
}
void init_st(){top=-1;for(int i=1;i<=n;i++)idx[i]=i;
}
void dfs(int u){if(book[u])return;book[u]=true;if(L[u]!=-1){dfs(L[u]);dp[u]=max(dp[u],(ll)abs(g[u]-g[L[u]])+dp[L[u]]);}if(R[u]!=-1){dfs(R[u]);dp[u]=max(dp[u],(ll)abs(g[u]-g[R[u]])+dp[R[u]]);}
}
int main(){scanf("%d",&t);while(t--){scanf("%d",&n);init();for(int i=1;i<=n;i++) scanf("%d",&h[i]);for(int i=1;i<=n;i++)scanf("%d",&g[i]);//得到某点向左走能走到的第一个点 //用单调栈维护递减序列 init_st();for(int i=1;i<=n;i++){while(top!=-1&&h[st[top]]<=h[i]){if(h[st[top]]==h[i])idx[i]=idx[st[top]];//同样高度,选择离得更远的 top--;}if(top==-1)//top==-1说明左边没有比当前点更高的了L[i]=-1;elseL[i]=idx[st[top]];st[++top]=i;}init_st();//得到某点向右走能走到的第一个点 //用单调栈倒着维护递减序列 for(int i=n;i>=1;i--){while(top!=-1&&h[st[top]]<=h[i]){if(h[st[top]]==h[i])idx[i]=idx[st[top]];//同样高度,选择离得更远的 top--;}if(top==-1)//top==-1说明右边没有比当前点更高的了R[i]=-1;elseR[i]=idx[st[top]];st[++top]=i;}for(int i=1;i<=n;i++){if(!book[i])dfs(i);}for(int i=1;i<=n;i++){if(i!=1){printf(" ");}printf("%lld",dp[i]);}printf("\n");}
}

K 蹦蹦炸弹--模拟

题目链接:

K-蹦蹦炸弹_哈尔滨理工大学第12届程序设计竞赛(同步赛) (nowcoder.com)

思路:

由于所有炸弹都在x轴上,所以每次炸弹相遇只在相邻的两颗炸弹之间发生。那么我们把相邻两颗炸弹的相遇时间放进优先队列里,每次把堆顶的两颗炸弹删掉,然后找到这两颗炸弹左右两边的炸弹(set模拟),把它们的相遇时间放进优先队列里不断模拟就好了。

代码:

#include <bits/stdc++.h>using namespace std;const double inf=1e9;
const int N=1e5+10;
bool book[N];
int ans[N];
set<int> s;
typedef struct dot{int x,v,id;
}dot;
dot p[N];
bool cmp(dot a,dot b){return a.x<b.x;
}
typedef struct Node{double t;int x,y;bool operator<(const Node& a)const{return t>a.t;}
}Node;
priority_queue<Node> pq;
double cal(int i,int j){double dis=(p[j].x-p[i].x)*1.0;if(p[i].v==0){if(p[j].v<0)return dis/(-p[j].v);elsereturn inf;}if(p[j].v==0){if(p[i].v>0)return dis/p[i].v;elsereturn inf;}if(p[i].v<0&&p[j].v>0){return inf;}else if(p[i].v>0&&p[j].v>0){if(p[i].v>p[j].v)return dis/(p[i].v-p[j].v);else return inf;}else if(p[i].v<0&&p[j].v<0){if(p[i].v>p[j].v)return dis/(p[i].v-p[j].v);else return inf;}else{return dis/(p[i].v-p[j].v);}
}
int main(){int n;scanf("%d",&n);for(int i=0;i<=n+1;i++){s.insert(i);}for(int i=1;i<=n;i++){scanf("%d",&p[i].x);p[i].id=i;}for(int i=1;i<=n;i++){scanf("%d",&p[i].v);}sort(p+1,p+n+1,cmp);for(int i=2;i<=n;i++){Node tmp;tmp.x=i-1;tmp.y=i;tmp.t=cal(i-1,i);pq.push(tmp);}Node tp,tmp;while(!pq.empty()){tp=pq.top();pq.pop();if(tp.t==inf){break;}if(book[tp.x]||book[tp.y])continue;book[tp.x]=book[tp.y]=true;int l,r,ll,rr;auto iter=s.find(tp.x);l=*prev(iter);s.erase(iter);iter=s.find(tp.y);r=*next(iter);s.erase(iter);if(l==0||r==n+1)continue;tmp.x=l,tmp.y=r;tmp.t=cal(l,r);pq.push(tmp);}int cnt=0;for(auto iter=s.begin();iter!=s.end();iter++){if(*iter!=0&&*iter!=n+1){ans[++cnt]=p[*iter].id;}}sort(ans+1,ans+cnt+1);printf("%d\n",cnt);for(int i=1;i<=cnt;i++){printf("%d\n",ans[i]);}
}

哈尔滨理工大学第12届程序设计竞赛--ADK题相关推荐

  1. 哈尔滨理工大学第七届程序设计竞赛初赛 题集

    1. 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 这是mengxiang000和Tabri ...

  2. 科林明伦杯”哈尔滨理工大学第十届程序设计竞赛B(减成1)

    科林明伦杯"哈尔滨理工大学第十届程序设计竞赛 存在n个数,每次操作可以任选一个区间使得区间内的所有数字减一.问最少多少次操作,可以让所有数都变成1. 数据保证一定有解. 输入描述: 输入t, ...

  3. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解

    "科林明伦杯"哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解 萌新又来写题解啦 原题链接 B 减成一 题意:存在n个数,每次操作可以任选一个区间使得区间内的所有数字减一.问最少多 ...

  4. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛 E 赛马 python

    "科林明伦杯"哈尔滨理工大学第十届程序设计竞赛 E 赛马 python E 好家伙 田忌赛马真就 匹配就不解释了 思路,主要咱不止一匹马 所以就最好的比 对方比这个数小的即可 所以 ...

  5. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛)---全题目+题解

    文章目录 A.点对最大值 B.减成一 C.面积 D.扔硬币 E.赛马 F.三角形 G.养花 H.直线 I.字典序 J.最大值 A.点对最大值 链接:https://ac.nowcoder.com/ac ...

  6. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛) 点对最大值 dp

    链接:https://ac.nowcoder.com/acm/contest/5758/A 来源:牛客网 题目描述 这里有一棵树,每个点和每条边都存在一个价值.对于树上点对的价值,包括点对的起点和终点 ...

  7. 哈尔滨理工大学第七届程序设计竞赛决赛(网络赛-高年级组)G - 幼儿园战争...

    题目描述 幼儿园的孩子们正在做游戏,每个人都有自己的帮派,帮派之间打架,然后赢者吞并弱者扩大自己的势力.最开始每个孩子的帮派中只有自己,然后接下来有会有两个人打架,这两个人会集结自己所属的势力开始打架 ...

  8. 哈尔滨理工大学第七届程序设计竞赛初赛(高年级组)题解

    比赛链接:https://www.nowcoder.com/acm/contest/27#question A: 小Z的体型实在是太胖了,每次和小D一起出门都跟不上小D的脚步,这让小Z很气馁,于是小Z ...

  9. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛) F

    F 三角形 链接:https://ac.nowcoder.com/acm/contest/5758/F 来源:牛客网 小明有一根长度为a的木棒,现在小明想将木棒分为多段(每段木棒长度必须为整数), 使 ...

最新文章

  1. Linux命令之more
  2. Android布局之LinearLayout
  3. html ie乱码_Java 0基础入门(初识Html)
  4. 打开cmd窗口新技巧get
  5. php向前截取字符串函数,ThinkPHP 模板substr的截取字符串函数详解
  6. Docker学习总结(10)——10分钟玩转Docker
  7. 初识Opserver,StackExchange的监控解决方案
  8. java域名解析到目录_nginx将泛解析的匹配域名绑定到子目录配置方法
  9. pyspark调用spark以及执行带in语句参数的hql示例
  10. 独立站的SEO搜索引擎优化
  11. Linux debian利用ifconfig查看IP地址
  12. 统计一个字符串中单词的个数(C语言)
  13. android手机存储空间猛增,为什么安卓手机运行内存和储存空间增长速度这么快,什么原因呢?...
  14. Form通过js提交
  15. 工业元宇宙三人行系列直播活动第五场在北京举办
  16. Java程序完形填空题_完形填空:-_JavaDeveloper-51CTO博客
  17. 用C语言开发NES游戏(CC65)15、音乐
  18. 小米手机远程管理服务器,买小米手机都不用这4个功能,买了也白买
  19. win+l不能锁定计算机
  20. Geant4学习之能谱输入

热门文章

  1. C++ openssl ECDSA签名
  2. 开关电源测试软件有哪些,请问开关电源的测试仪器都有哪些
  3. 重磅新品3D打印机“智能微工厂”CP-01引全球关注,本周强势登陆
  4. python桌面宠物_写个桌面挂件 | 手把手带大家做只桌面宠物呗
  5. POJ - Wall(凸包周长)
  6. 阿里P8架构大咖顷情力荐,“Java全线成长宝典”,从p5到p8一应俱全,跳槽大厂,弯道超车
  7. 微信免签支付java_2019最新个人免签(支付宝、微信、QQ钱包)支付系统java易语言...
  8. 单片机毕业设计 智能门禁系统
  9. vb.net 生成条码 (code39)
  10. .net framework3.5无法安装解决办法