上次做过类似的题,原来这道还要简单些??

上次那道题是每天可以同时买进卖出,所以用两个优先队列,一个存买进,一个存卖出(供反悔的队列)。

这道题实际上用一个就够了???但是不好理解!!

所以我还是用了俩...

和之前那道题不同的是,如果我选择了反悔,之前第二个队列的队头就完全没有用了,但是我们可以选择重新买它,所以把它重新放到第一个队列。

#include<bits/stdc++.h>
using namespace std; priority_queue < int, vector < int >, greater < int > > q1, q2; int n, a[];
long long ans; int main() {
freopen("trade.in", "r", stdin);
freopen("trade.out", "w", stdout);
scanf("%d", &n);
for(int i = ; i <= n; i ++) scanf("%d", &a[i]);
for(int i = ; i <= n; i ++) {
int x1, x2, r1 = , r2 = ;
if(!q1.empty()) {
x1 = q1.top(); if(a[i] - x1 > ) r1 = a[i] - x1;
}
if(!q2.empty()) {
x2 = q2.top(); if(a[i] - x2 > ) r2 = a[i] - x2;
}
if(r1 >= r2 && r1) {
q1.pop(); q2.push(a[i]); ans += r1;
} else if(r2 > r1 && r2 ) {
q2.pop(); q2.push(a[i]); q1.push(x2); ans += r2;
} else q1.push(a[i]);
}
printf("%lld", ans);
return ;
}

这道题乍一看是推公式$O(1)$的数论??经$yuli$dalao考场上一个多小时的测试发现没有这样的式子....

所以$zc$dalao通过研究打表发现了正解!其实是莫队!

???

首先我们也来打一下表....发现了两个递推式:$S_n^m=S_n^{m-1}+C_n^m$和$S_n^m=2S_{n-1}^m-C_{n-1}^m$,我们可以把$[n,m]$看成一个区间来进行离线莫队转移,复杂度$O(n\sqrt{n})$。

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
using namespace std; int blo[]; struct Node {
int n, m, id;
} qus[];
bool cmp(Node a, Node b) { if(blo[a.m] == blo[b.m]) return a.n < b.n; return a.m < b.m; } LL fac[], inv[];
LL C(int n, int m) {
if(m > n) return ;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
} LL mpow(LL a, LL b) {
LL ans = ;
for(; b; b >>= , a = a * a % mod)
if(b & ) ans = ans * a % mod;
return ans;
} void init() {
fac[] = ; inv[] = , inv[] = ;
for(int i = ; i <= ; i ++)
fac[i] = fac[i - ] * i % mod;
for(int i = ; i <= ; i ++)
inv[i] = mpow(fac[i], mod - );
for(int i = ; i <= ; i ++) blo[i] = i/ + ;
} int Ans[];
int main() {
freopen("sum.in", "r", stdin);
freopen("sum.out", "w", stdout);
int id;
scanf("%d", &id);
init();
int T;
scanf("%d", &T);
for(int i = ; i <= T; i ++)
scanf("%d%d", &qus[i].n, &qus[i].m), qus[i].id = i;
sort(qus + , qus + + T, cmp); int n = qus[].n, m = qus[].m; LL ans = ;
for(int i = ; i <= m; i ++) ans = (ans + C(n, i)) % mod;
Ans[qus[].id] = ans;
for(int i = ; i <= T; i ++) {
while(qus[i].m < m) {
ans = (ans - C(n, m) + mod) % mod;
m --;
}
while(qus[i].n > n) {
ans = (2LL * ans % mod - C(n, m) + mod) % mod;
n ++;
}
while(qus[i].m > m) {
m ++;
ans = (ans + C(n, m)) % mod;
}
while(qus[i].n < n) {
n --;
ans = 1LL * (ans + C(n, m)) * inv[] % mod;
}
Ans[qus[i].id] = ans;
}
for(int i = ; i <= T; i ++) printf("%d\n", Ans[i]);
return ;
}

感觉这种题就算让我再做一次,也写不出来...重载什么的简直太难记了aaa!!

对于第一个询问,直接分别处理每行和每列就行了,每行就直接加,每列用差分处理。

如何查找联通块数量?

分别处理两种情况:

1)与下边相交对于上面的矩形,查找它下一排最后一个与它相交的矩形,向前枚举直到不相交,把相交的矩形连边。

2)与右边相交对于左边的矩形,查找它右边与它相交的所有矩形,连边。

以上操作用二分实现。注意的是,因为我们建边是在每排的基础上(因为查询的是排),所以第一种应该建在下面那排,第二种应该建在两个矩形上边界的排取max。(查询前缀时才能保证合法)

stl(vector简直tql!QAQ)

#include<bits/stdc++.h>
#define LL long long
using namespace std; int ans2[];
LL ans1[], sum2[], sum1[]; struct Data {
int lx, ly, rx, ry;
Data(int lx = , int ly = , int rx = , int ry = ) :
lx(lx), ly(ly), rx(rx), ry(ry) { }
} A[]; struct Node {
int id, l, r;
Node(int id = , int l = , int r = ) :
id(id), l(l), r(r) { }
}; vector < Node > row[], col[];
bool operator < (const Node &a, const Node &b) {
return a.l < b.l || (a.l == b.l && a.r < b.r);
} vector < pair < int , int > > G[]; int root[], edge, num;
int find(int x) {
if(root[x] != x) root[x] = find(root[x]);
return root[x];
} void merge(int x, int y) {
x = find(x); y = find(y);
if(x != y) root[x] = y, ++ edge;
} int main() {
freopen("building.in", "r", stdin);
freopen("building.out", "w", stdout);
int opt;
scanf("%d", &opt);
int n, m, k, p;
scanf("%d%d%d%d", &n, &m, &k, &p);
for(int i = ; i <= k; i ++) {
int lx, ly, rx, ry;
scanf("%d%d%d%d", &lx, &ly, &rx, &ry);
A[i] = Data(lx, ly, rx, ry);
row[lx].push_back(Node(i, ly, ry));
col[ly].push_back(Node(i, lx, rx));
if(lx == rx) sum1[lx] += (ry - ly + );
else sum2[lx] ++, sum2[rx + ] --;
}
for(int i = ; i <= n; i ++) sort(row[i].begin(), row[i].end());
for(int i = ; i <= m; i ++) sort(col[i].begin(), col[i].end());
for(int i = ; i <= k; i ++) {
int down = A[i].rx + ;
if(down <= n && row[down].size()) {
int p = upper_bound(row[down].begin(), row[down].end(), Node(, A[i].ry, m + )) - row[down].begin() - ;
for(; p >= && row[down][p].r >= A[i].ly; p --)
G[down].push_back(make_pair(i, row[down][p].id));
}
int right = A[i].ry + ;
if(right <= m && col[right].size()) {
if(right < ) return ;
int p = upper_bound(col[right].begin(), col[right].end(), Node(, A[i].rx, n + )) - col[right].begin() - ;
for(; p >= && col[right][p].r >= A[i].lx; p --)
G[max(A[i].lx, A[col[right][p].id].lx)].push_back(make_pair(i, col[right][p].id));
}
}
for(int i = ; i <= n; i ++) sum2[i] += sum2[i-];
for(int i = ; i <= n; i ++) {
sum2[i] += sum2[i-];
sum1[i] += sum1[i-];
ans1[i] = sum1[i] + sum2[i];
}
for(int i = ; i <= k; i ++) root[i] = i;
for(int i = ; i <= n; i ++) {
num += row[i].size();
for(int j = ; j < G[i].size(); j ++) merge(G[i][j].first, G[i][j].second);
ans2[i] = num - edge;
}
while(p --) {
int u, v;
scanf("%d%d", &u, &v);
if(u) printf("%d\n", ans2[v]);
else printf("%lld\n", ans1[v]);
}
return ;
}

【10.11校内测试】【优先队列(反悔贪心)】【莫队】【stl的应用??离线处理+二分】的更多相关文章

  1. 【8.30校内测试】【找规律模拟】【DP】【二分+贪心】

    对于和规律或者数学有关的题真的束手无策啊QAQ 首先发现两个性质: 1.不管中间怎么碰撞,所有蚂蚁的相对位置不会改变,即后面的蚂蚁不会超过前面的蚂蚁或者落后更后面的蚂蚁. 2.因为所有蚂蚁速度一样,不 ...

  2. 2018.10.29 bzoj4564: [Haoi2016]地图(仙人掌+莫队)

    传送门 根据原图建一棵新的树. 把原图每一个环上除了深度最浅的点以外的点全部向深度最浅的点连边. 然后可以搞出来一个dfsdfsdfs. 这个时候我们就成功把问题转换成了对子树的询问. 然后就可以对权 ...

  3. [CSP-S模拟测试]:sum(数学+莫队)

    题目传送门(内部题63) 输入格式 第一行有一个整数$id$,表示测试点编号.第一行有一个整数$q$,表示询问组数.然后有$q$行,每行有两个整数$n_i,m_i$. 输出格式 一共有$q$行,每行一 ...

  4. [CSP-S模拟测试]:飘雪圣域(莫队)

    题目描述 $IcePrincess\text{_}1968$和$IcePrince\text{_}1968$长大了,他们开始协助国王$IceKing\text{_}1968$管理国内事物. $IceP ...

  5. 联赛模拟测试12 C. sum 莫队+组合数

    题目描述 分析 \(80\) 分的暴力都打出来了还是没有想到莫队 首先对于 \(s[n][m]\) 我们可以很快地由它推到 \(s[n][m+1]\) 和 \(s[n][m-1]\) 即 \(s[n] ...

  6. SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)

    DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...

  7. 【11.5校内测试】【倒计时5天】【DP】【二分+贪心check】【推式子化简+线段树】

    Solution 非常巧妙的建立DP方程. 据dalao们说题目明显暗示根号复杂度??(反正我是没看出来 因为每次分的块大小一定不超过$\sqrt n$,要不然直接每个位置开一个块答案都才为$n$. ...

  8. 【10.7校内测试】【队列滑窗】【2-sat】【贪心+栈二分+线段树(noip模拟好题)】【生日祭!】

    比较好想的一道题,直接用队列滑窗,因为扫一遍往队列里加东西时,改变的只有一个值,开桶储存好就行了! #include<bits/stdc++.h> using namespace std; ...

  9. 【10.17校内测试】【二进制数位DP】【博弈论/预处理】【玄学(?)DP】

    Solution 几乎是秒想到的水题叻! 异或很容易想到每一位单独做贡献,所以我们需要统计的是区间内每一位上做的贡献,就是统计区间内每一位是1的数的数量. 所以就写数位dp辣!(昨天才做了数字统计不要 ...

随机推荐

  1. Spring4笔记12--SSH整合3--Spring与Struts2整合

    SSH 框架整合技术: 3. Spring与Struts2整合(对比SpringWeb): Spring 与 Struts2 整合的目的有两个: (1)在 Struts2 的 Action 中,即 V ...

  2. Django集成Xadmin list index out of range报错解决方案

    return self.render(context) File "C:\Python36\lib\site-packages\django\template\defaulttags.py& ...

  3. 十、springcloud之Consul注销实例

    @Autowired //com.ecwid.consul.v1.ConsulClient private ConsulClient consulClient; @PostMapping(" ...

  4. mac 升级10.12 php debug 环境 跑不起的解决 解决方案

    1:  mac 升级后发现 php从原来的5.5  升级为 5.6 了...   所以以前 php.ini 里面的配置全部都没有了. mac 给我们做了备份2:  没办法只能升级php对应的插件到5. ...

  5. 19 Error handling and Go go语言错误处理

    Error handling and Go go语言错误处理 12 July 2011 Introduction If you have written any Go code you have pr ...

  6. 【前端vue开发架构】vue开发单页项目架构总结

    为营销活动设计的前端架构 主要的技术栈为 Vuejs,Webpack,请自行阅读如下技术或者框架的文档: 一.基础说明: node (https://nodejs.org/en/) npm (http ...

  7. robotframework-ride多次运行,有时候不显示日志信息

    解决方法: 修改"C:\Python27\lib\site-packages\robotide\contrib\testrunner\testrunner.py"文件pop方法中  ...

  8. 应用服务器中对JDK的epoll空转bug的处理

    原文链接:应用服务器中对JDK的epoll空转bug的处理 前面讲到了epoll的一些机制,与select和poll等传统古老的IO多路复用机制的一些区别,这些区别实质可以总结为一句话, 就是epol ...

  9. ld 脚本浅析-LD手册粗糙翻译

    本文乃转载, 我在其基础上做了少量修改. 原作者的E-mail是zhanglei@sict.ac.cn. 完成于2005.11.5-2005.11.8 0. Contents 1. 概论2. 基本概念 ...

  10. Java 常用的几个lambda表达式

    Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift,C#等都已经支 ...