G,http://acm.uestc.edu.cn/#/problem/show/1598

题意:给你一个n个元素的序列,支持以下操作:单点修改,查询区间内连续的最大子段和。

解法:线段树每个结点维护四个域:maxv,maxl,maxr,sumv,其中sumv为该区间的和,maxv为该区间上的最大子段和,maxl为必须包含左端点的最大子段和,maxr为必须包含右端点的最大子段和。之后我们用lc和rc表示左子节点和右子节点。

修改时:
1、若 lc.maxr 和 rc.maxl 都为负,就从中取较大的为该节点的maxv(防止一个都不取),反之取二者中正的(都正就都取)。
2、将该节点的 maxv 用 lc 和 rc 的 maxv 更新。
3、该节点的 maxl 为 max { lc.maxl ,  lc.sumv + rc.maxl }。
4、该节点的 maxr 为 max { rc.maxr , rc.sumv + lc.maxr }。
5、该节点的 sumv 为 lc.sumv + rc.sumv 。

查询时:
按照修改的方式将询问区间覆盖的结点信息合并即可。


#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
struct node{int l,r,lm,rm,mx,sum;
}tree[maxn<<2];
int n,m,a[maxn];
void pushup(int rt){tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;tree[rt].lm=max(tree[rt<<1].lm,tree[rt<<1].sum+tree[rt<<1|1].lm);tree[rt].rm=max(tree[rt<<1|1].rm,tree[rt<<1].rm+tree[rt<<1|1].sum);tree[rt].mx=max(max(tree[rt<<1].mx,tree[rt<<1|1].mx),tree[rt<<1].rm+tree[rt<<1|1].lm);
}
void build(int l, int r, int rt){tree[rt].l=l,tree[rt].r=r;if(l==r){tree[rt].sum=tree[rt].lm=tree[rt].rm=tree[rt].mx=a[l];return;}int mid=(l+r)/2;build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);pushup(rt);
}
void update(int pos, int val, int rt){if(tree[rt].l==tree[rt].r){tree[rt].sum=tree[rt].lm=tree[rt].rm=tree[rt].mx=val;return;}int mid=(tree[rt].l+tree[rt].r)/2;if(pos<=mid) update(pos,val,rt<<1);else update(pos,val,rt<<1|1);pushup(rt);
}
node query(int L, int R, int rt){if(L<=tree[rt].l&&tree[rt].r<=R){return tree[rt];}int mid=(tree[rt].l+tree[rt].r)/2;if(R<=mid) return query(L,R,rt<<1);else if(L>mid) return query(L,R,rt<<1|1);else{node a,g,h;g=query(L,mid,rt<<1);h=query(mid+1,R,rt<<1|1);a.mx=max(max(g.mx,h.mx),g.rm+h.lm);a.rm=max(h.rm,g.rm+h.sum);a.lm=max(g.lm,g.sum+h.lm);return a;}
}
int main()
{int n, m;while(~scanf("%d%d",&n,&m)){for(int i=1; i<=n; i++) scanf("%d", &a[i]);build(1,n,1);while(m--){int op,l,r;scanf("%d %d %d", &op, &l, &r);if(op==1){printf("%d\n", query(l,r,1).mx);}else{update(l,r,1);}}}return 0;
}

H,http://acm.uestc.edu.cn/#/problem/show/1581

题意:给你一个n个元素的序列,支持以下操作:单点修改,查询某个下标是等差数列的子序列的最小值

解法:乱搞题。设置一个阈值K,

当公差>K的时候,可以暴力计算答案。我这里设成5就过了。
当公差小于K的时候,对每一个公差d,及其所有小于等于d的首项,建立一棵线段树。注意,公差确定时,每个首项对应的线段树是没有交集的。
共O(K2)棵线段树,总空间为O(K*n)。
询问时,找到它究竟在哪棵线段树。
修改时,在K棵线段树中进行修改。


#include <bits/stdc++.h>
using namespace std;
const int maxn=70010;
int n,m,a[maxn],pos1[6][maxn],pos2[6][maxn];
struct seg{int c, tree[maxn<<2];void pushup(int rt){tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);}void build(int l, int r, int rt){if(l==r){tree[rt]=a[pos2[c][l]];return;}int mid=(l+r)/2;build(l,mid,rt*2);build(mid+1,r,rt*2+1);pushup(rt);}void update(int pos, int l, int r, int rt){if(l==r){tree[rt]=a[pos2[c][l]];return;}int mid=(l+r)>>1;if(pos<=mid) update(pos,l,mid,rt<<1);else update(pos,mid+1,r,rt<<1|1);pushup(rt);}int query(int L, int R, int l, int r, int rt){if(L<=l&&r<=R){return tree[rt];}int mid=(l+r)>>1;if(R<=mid) return query(L,R,l,mid,rt<<1);else if(L>mid) return query(L,R,mid+1,r,rt<<1|1);else{return max(query(L,mid,l,mid,rt<<1),query(mid+1,R,mid+1,r,rt<<1|1));}}
}T[6];int main()
{while(~scanf("%d", &n)){for(int i=1; i<=n; i++) scanf("%d", &a[i]);for(int i=1; i<=5; i++){int now=1,tot=1;for(int j=1; j<=n; j++){pos1[i][now]=j;pos2[i][j]=now;now+=i;if(now>n) now=++tot;}T[i].c=i;T[i].build(1,n,1);}scanf("%d", &m);while(m--){int op,x,y;scanf("%d %d %d",&op,&x,&y);if(op==0){a[x]+=y;for(int i=1; i<=5; i++){T[i].update(pos1[i][x],1,n,1);}}else{if(y<=5){int r=pos1[y][x]+(n-x)/y;printf("%d\n", T[y].query(pos1[y][x],r,1,n,1));}else{int ans=a[x];for(int i=x; i<=n; i+=y){ans=max(ans,a[i]);}printf("%d\n",ans);}}}}return 0;
}

I,http://acm.uestc.edu.cn/#/problem/show/1603

题意:现在有一个序列 a1,a2,...,an ,相应将其分成若干个 heapable 的子序列,问使得子序列个数最少的策略。

解法如下:

用set维护,set中存储的是个pair第一维权值,第二维是在原序列的下标。
贪心地从前往后扫,每到一个元素,就查找之前的元素中小于等于其的最大的元素//it=Set.lower_bound(pair<a[i],i>);it--;//,如果存在,就将它置为其父亲。如果一个结点已经是两个儿子的父亲了,就不能在set中存在了,就将他删除。如果然后将当前元素插入。
pair的比较函数是双关键字比较,先按第一关键字,如果相同,再按第二关键字。
如果不存在,就直接将当前元素插入。
证明是比较显然的,因为对于某个元素,前面各个堆中权值相同的结点都是等价的。
输出答案时用邻接表/*vector<int>G[N];*/把树存下来,跑个dfs,然后排个序输出就行。

复杂度:O(n*log(n)*log(n))


#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, cnt, a[maxn], son[maxn];
vector <int> G[maxn];
struct node{int first,second;
};
bool operator<(node x, node y){if(a[x.second]==a[y.second]) return x.second<y.second;return a[x.second]<a[y.second];
}
set<node>s;int main()
{int T;scanf("%d",&T);while(T--){s.clear();cnt=0;scanf("%d", &n);memset(son,0,sizeof(son));//for(int i=0; i<maxn; i++) G[i].clear();for(int i=1; i<=n; i++){scanf("%d",&a[i]);node now;now.second=i;set<node>::iterator it=s.upper_bound(now);if(it==s.begin()){G[cnt].push_back(i);now.first=cnt,now.second=i;s.insert(now);cnt++;}else{it--;now=*it;son[now.second]++;if(son[now.second]==2) s.erase(it);now.second=i;s.insert(now);G[now.first].push_back(i);}}printf("%d\n", cnt);for(int i=0; i<cnt; i++){printf("%d",G[i].size());for(int j=0; j<G[i].size(); j++){printf(" %d", G[i][j]);}printf("\n");G[i].clear();}}return 0;
}

J,http://acm.uestc.edu.cn/#/problem/show/1599

题意:给你n个数,你每次可以合并两个数,合并所得的数是原来两个数之和,合并的代价也是原来两个数之和。n-1次合并后只剩一个数,问你该过程的最小代价。
解法:贪心 用堆来维护,将所有元素放进堆。 每次取出当前最小的两个元素,将其合并,统计答案,放回堆。重复n-1次。比较显然,先合并小的,再合并大的明显更优。


#include <bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n, x, ans;
int main()
{while(~scanf("%d", &n)){ans=0;while(!q.empty()) q.pop();for(int i=1; i<=n; i++){scanf("%d", &x);q.push(x);}while(q.size()>1){int cur = q.top(); q.pop();int cur1 = q.top(); q.pop();ans += cur+cur1;q.push(cur+cur1);}printf("%d\n", ans);}return 0;
}

UESTC数据结构专题训练 G,H,I,J相关推荐

  1. 如果令 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 分别等于

    如果令 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 分别等于 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  2. 黑龙江农垦科技职业学院喜迎寒假多校联赛2 A,C,F,G,H,I,J题解

    黑龙江农垦科技职业学院喜迎寒假多校联赛2 (欢 乐 A K 场) A,C,F,G,H,I,J题解 题目链接 A. 由于该题数据过大 首先就要使用到快读 不然会超时 快读模板以及解析(转载) 如果直接使 ...

  3. 2015 UESTC 数据结构专题H题 秋实大哥打游戏 带权并查集

    秋实大哥打游戏 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 Descr ...

  4. 2015 UESTC 数据结构专题G题 秋实大哥去打工 单调栈

    秋实大哥去打工 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 Descr ...

  5. 2015 UESTC 数据结构专题N题 秋实大哥搞算数 表达式求值/栈

    秋实大哥搞算数 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1074 Des ...

  6. 2015 UESTC 数据结构专题D题 秋实大哥与战争 变化版本的线段树,合并区间,单点查询...

    D - 秋实大哥与战争 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 D ...

  7. 2015 UESTC 数据结构专题A题 秋实大哥与小朋友 线段树 区间更新,单点查询,离散化...

    秋实大哥与小朋友 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 Desc ...

  8. 2021年度训练联盟热身训练赛第五场(A B C E F G H I)

    比赛链接 目录 OP A Binary Seating 思路 代码 B Cutting Corners 思路 代码 C Ducky Debugging 思路 代码 E Figure Skating 思 ...

  9. 并查集算法总结专题训练

    并查集算法总结&专题训练 1.概述 2.模板 3.例题 1.入门题: 2.与别的算法结合: 3.考思维的题: 4.二维转一维: 5.扩展域并查集&边带权并查集: 4.总结 1.概述 并 ...

最新文章

  1. [源码和文档分享]基于Netty和WebSocket的Web聊天室
  2. 递归实现牛顿法求整数平方根(原理: 给一个初始值(比如X1 = a/2)迭代求a的平方根,设定一个误差限,不断逼近a X1 = a/2 X2 = (X1+a/X1)/
  3. 一 Storm 基础
  4. java中byte转string的方法有哪些?
  5. 整体管理6个过程及相关重点
  6. GridView实现删除时弹出确认对话框
  7. access查询出生日期格式转换_从身份证中提取出生日期的3个方法和计算年龄和星座的方法...
  8. 弱监督学习下商品识别:CVPR 2018细粒度识别挑战赛获胜方案简介
  9. 搭载鸿蒙的油烟机,华为、美的合作:搭载鸿蒙系统的家电来了 三大亮点
  10. 机器学习之PCA原理
  11. 维权靠微博?用户京东金融账户被盗刷15万 处理未果怒发微博曝光
  12. Protel99se信号完整性的最新应用
  13. java多线程读取分割的文件_java多线程批量读取文件(二)--读写分离
  14. 学会这些Sketchup技巧,工作效率提高一半
  15. PDF破解FileOpenPlugin加密的方法
  16. make 及 make clean 的作用
  17. 关于英伟达显卡驱动程序(GeForce)无法下载的问题
  18. Cumt2020九月校赛 by 水一水
  19. 《第五项修炼》读后感
  20. python3文本文件读取方法_Python3读取文件常用方法实例分析

热门文章

  1. [CQOI 2010]扑克牌
  2. 【MATLAB项目实战】基于Morlet小波变换的滚动轴承故障特征提取研究
  3. linux sudo 权限_在Linux中使用sudo委派权限
  4. Java - 三种基本的设计模式
  5. VS2019 community版本下载Extension太慢解决方案
  6. splice()方法采坑
  7. 全国计算机职称考试难点,计算机职称考试模块考试难点autocad2004.doc
  8. 数项级数——(一)级数的收敛性
  9. 笔记本WiFi无法连接、网卡驱动无法安装
  10. imindmap之云朵技巧