博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
无题5
阅读量:5150 次
发布时间:2019-06-13

本文共 5495 字,大约阅读时间需要 18 分钟。

 

第一题:线段树求最大连续子段和,维护四个信息:区间最大子段和, 区间和, 左边最大子段和, 右边最大子段和;

查询的时候返回的是一个指针,我开始用的zero, 节约空间, 后来发现会同时有多个询问用到zero,zero会不断变化, 所以要tail++,或重新写一个up函数

 

#include
using namespace std;const int M = 5 * 1e5 + 10;int n, m, inf = 2e9;int a[M];struct Node{ int sum[5]; Node *ls, *rs; void up(){ sum[3] = ls->sum[3] + rs->sum[3]; sum[2] = max(ls->sum[2], rs->sum[2]); sum[2] = max(ls->sum[1] + rs->sum[0], sum[2]); sum[0] = max(ls->sum[0], ls->sum[3] + rs->sum[0]); sum[1] = max(rs->sum[1], ls->sum[1] + rs->sum[3]); } }pool[M << 2], *tail = pool, *root, *zero;Node * build(int lf = 1, int rg = n){ Node *nd = ++tail; if(lf == rg) { nd->sum[0]= nd->sum[1] = nd->sum[2] = nd->sum[3] = a[lf]; } else { int mid = (lf + rg) >> 1; nd->ls = build(lf, mid); nd->rs = build(mid + 1, rg); nd->up(); } return nd;}#define Ls lf, mid, nd -> ls#define Rs mid+1, rg, nd -> rsvoid modify(int pos, int val, int lf = 1, int rg = n, Node * nd = root){ if(lf == rg){ nd->sum[0]= nd->sum[1] = nd->sum[2] = nd->sum[3] = val; } else { int mid = (lf + rg) >> 1; if(pos <= mid) modify(pos, val, Ls); else modify(pos, val, Rs); nd->up(); }}Node * query(int L, int R, int lf = 1, int rg = n, Node * nd = root){ if(L <= lf && rg <= R) return nd; else { int mid = (lf + rg) >> 1; int t1 = 0, t2 = 0; if(R <= mid) return query(L, R, Ls); if(L > mid) return query(L, R, Rs); Node * a1 = query(L, R, Ls); Node * a2 = query(L, R, Rs); Node * a3 = ++tail; a3->ls = a1; a3->rs = a2; a3->up(); return a3; }}int main(){ freopen("BRS.in","r",stdin); freopen("BRS.out","w",stdout); zero = ++tail; zero->ls = zero->rs = zero; zero->sum[0] = zero->sum[1] = zero->sum[2] = zero->sum[3] = 0; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++)scanf("%d", &a[i]); root = build(); int opt, x, y; while(m--){ scanf("%d%d%d", &opt, &x, &y); if(opt == 1){ Node * ans = query(x, y); int ret = ans->sum[2]; printf("%d\n", ret); } else modify(x, y); }}
View Code

 

 

 

第二题:矩阵快速幂,首先DP方程容易得:dp[s] = dp[s - 1] + dp[s - 2] + dp[s - 3] + ……+ dp[s - k];

s巨大,转移又一样,矩阵快速幂;

第一行全部赋成1, 表示dp[s] = dp[s - 1] + dp[s - 2] + dp[s - 3] + ……+ dp[s - k]; 然后每行都把原来的移过去;

转移矩阵如下:

 

转移矩阵做 n - k 次相当于走了n-k步, 最初的矩阵就是dp数组dp[i] 再走k步就可以了;

#include
using namespace std;#define ll long longconst ll mod = 7777777;int K; ll dp[15];inline ll moc(ll a){ if(a>=mod) a-=mod; return a;}struct Mat{ ll w[15][15]; void unit(){ for(int i = 1; i <= K; i++) for(int j = 1; j <= K; j++) w[i][j] = (i == j); } void init(){ for(int i = 1; i <= K; i++) for(int j = 1; j <= K; j++) w[i][j] = 0; }}ori;Mat operator * (const Mat &s, const Mat &t){ Mat ret; ret.init(); for(int i = 1; i <= K; i++) for(int j = 1; j <= K; j++) for(int k = 1; k <= K; k++) ret.w[i][j] = moc(ret.w[i][j] + 1ll * s.w[i][k] * t.w[k][j] % mod); return ret;}Mat ksm(Mat a, int b){ Mat ret; ret.unit(); for(; b; b >>= 1, a = a * a) if(b & 1) ret = ret * a; return ret;}void w(Mat a){ for(int i=1;i<=K;i++) { for(int j=1;j<=K;j++) cout<
<<" "; cout<
View Code

 

第三题:扫描线,注意断点问题, 线段树f[o](lf -- rg) 保存的其实是y[rg] -  y[lf - 1], 不然合并的时候中间会漏掉, 所以开始的时候左区间+1; 

#include
using namespace std;const int M = 10005;int n, q;#define ll long longint yy[M*2];struct Event{ int x, y1, y2; int d;};vector
e;struct Node { int sum; int cnt; Node *ls , *rs; void up(int l, int r){ if(cnt) sum = yy[r] - yy[l-1]; else if(l != r) sum = ls->sum + rs->sum; else sum = 0; }}pool[M << 4], *root, *tail = pool;Node *build(int l = 1, int r = q){ Node * nd = ++tail; if(l == r)nd->sum = 0, nd->cnt = 0; else { int mid = (l + r) >> 1; nd->ls = build(l, mid); nd->rs = build(mid + 1, r); nd->up(l ,r); } return nd;}#define Ls l, mid, nd -> ls#define Rs mid+1, r, nd -> rsvoid modify(int L, int R, int d, int l = 1, int r = q, Node * nd = root){ if(L <= l && R >= r)nd->cnt += d, nd->up(l , r); else { int mid = (l + r) >> 1; if(L <= mid)modify(L, R, d, Ls); if(R > mid)modify(L, R, d, Rs); nd -> up(l, r); }}bool operator < (const Event &a, const Event &b){ return a.x < b.x;}int main(){ freopen("olddriver.in","r",stdin); freopen("olddriver.out","w",stdout); scanf("%d", &n); int cnt = 0; ll ans = 0; for(int i = 1; i <= n; i++){ int x1, x2, y1, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); e.push_back((Event){x1, y1, y2, 1}); e.push_back((Event){x2, y1, y2, -1}); yy[++cnt] = y1; yy[++cnt] = y2; } sort(yy+1, yy+1+cnt); sort(e.begin(), e.end()); q = unique(yy+1, yy+1+cnt) - yy - 1; root = build(); for(int i = 0; i < 2*n; i++){ int dx = i == 0 ? 0 : e[i].x - e[i - 1].x; ans += 1LL*root->sum * dx; int p1 = find(yy+1, yy+1+q, e[i].y1) - yy; int p2 = find(yy+1, yy+1+q, e[i].y2) - yy; modify(p1+1, p2, e[i].d); //cout<
<
View Code

 

转载于:https://www.cnblogs.com/EdSheeran/p/9688024.html

你可能感兴趣的文章
STM32硬件IIC操作
查看>>
Vue的v-for与v-if的联系
查看>>
设计模式之迭代器模式
查看>>
MySQL事务-ROLLBACK,COMMIT用法详解
查看>>
C#相关知识总结
查看>>
租房子多条件查询练习
查看>>
SVN服务器搭建和使用
查看>>
android 设置背景图片 xml的background和java的getDrawable()
查看>>
HZNU 2019 Summer training 4
查看>>
js实现数字每三位加逗号的方法
查看>>
域名和ip不能访问的原因
查看>>
2017最新PHP经典面试题目汇总(上篇)
查看>>
Java自学基础用法
查看>>
解决 /dev/mapper/centos-root 空间不足的问题
查看>>
Asp.Net在多线程环境下的状态存储问题
查看>>
Cisco配置aaa验证
查看>>
css3实现旋转卡片
查看>>
Python_生成器generator
查看>>
python__int 部分内部功能介绍
查看>>
nginx / apache / tomcat /resin等 http server的benchmark性能测试方法
查看>>