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

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

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

所以我还是用了俩...

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

#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. Once you eliminate all the other factors,the only thing remaining must be the truth.

    Once you eliminate all the other factors,the only thing remaining must be the truth. 一旦你排除了杂因,剩下的一定是 ...

  2. Permutation Index I & II

    Given a permutation which contains no repeated number, find its index in all the permutations of the ...

  3. a标签、img图片、iframe、表单元素、div

    1.<a href="http://www.baidu.com" target=''_blank">百度</a>  超链接标签 2.<img ...

  4. RabbitMQ--work queues(二)

    封装一个task到一个message,并发送到queue.consumer会去除task并执行这个task. 这里我们简化了操作,发送消息到队列中,consumer取出消息计算里面'.'号有几个就sl ...

  5. Python_oldboy_自动化运维之路(二)

    本节内容: 1.pycharm工具的使用 2.进制运算 3.表达式if ...else语句 4.表达式for 循环 5.break and continue 6.表达式while 循环 1.pycha ...

  6. 题解 P1074 【靶形数独 】

    这是一神题!!! 可能是因为我太弱了,题解都看不太懂QWQ 不过感谢wng老师的提醒,我写出了这个样的的代码. 分析: 这道题是一个搜索(dfs).很神奇很暴力的题 首先,你需要看懂题目.(可以先去玩 ...

  7. algorithm之unique

    #include<iostream> #include<algorithm> usingnamespace std; /**< unique函数的算法思想 */ vect ...

  8. Linux学习笔记:nohup & 后台任务

    在linux中,使用nohup xxx.sh &可以将前台任务变成后台任务执行,如果只使用&的话,在突然断网或者关闭启动终端时,内核会向后台任务发送sighup信号,从而导致后台任务停 ...

  9. Ninject中调用webapi卡住的情况解决

    过年这两天在家做项目,把mvc升级到了5.1,webapi升级到了2.1,忽然发现一个问题,在某些页面上ajax调用webapi时会发现卡死现象,CPU也没有被占用,就是网页一些在加载也不报错,经过2 ...

  10. 安装部署Apache Hadoop (完全分布式模式并且实现NameNode HA和ResourceManager HA)

    本节内容: 环境规划 配置集群各节点hosts文件 安装JDK1.7 安装依赖包ssh和rsync 各节点时间同步 安装Zookeeper集群 添加Hadoop运行用户 配置主节点登录自己和其他节点不 ...