51NOD 算法马拉松8
题目戳这里:51NOD算法马拉松8
某天晚上kpm在玩OSU!之余让我看一下B题...然后我就被坑进了51Nod...
A.还是01串
水题..怎么乱写应该都可以。记个前缀和然后枚举就行了.时间复杂度O(N)
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int maxn = 1000009; char s[maxn];
int sum[maxn], N; int main() {
// freopen("test.in", "r", stdin); memset(sum, 0, sizeof sum); scanf("%s", s);
N = strlen(s);
sum[N] = 0;
for(int i = N; i--; )
sum[i] = sum[i + 1] + (s[i] == '1');
if(!sum[0]) {
puts("0"); return 0;
}
if(sum[0] == N) {
printf("%d\n", N); return 0;
}
for(int i = 1; i < N; i++) if(sum[0] - i == - sum[N]) {
printf("%d\n", i); return 0;
}
puts("-1"); return 0;
}
B.差和问题
题目大意:维护一个集合S,支持加入/删除元素v, 询问S里面的元素两两之差绝对值之和.N,Q≤100000.
拆掉绝对值, 每次我们加入或者删除x时,用平衡树维护x对答案的贡献即可,时间复杂度O(NlogN)
(PS.官方题解好像是离散化+树状数组..常数应该小一点..我一开始没加读入优化还被卡TLE了2个点..)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<queue> using namespace std; typedef long long ll; const int maxn = 200009; int read() {
char c = getchar();
int ret = 0;
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
} struct Node { Node* ch[2];
ll sum;
int r, v, s; void upd() {
s = ch[0]->s + ch[1]->s + 1;
sum = ch[0]->sum + ch[1]->sum + v;
} } pool[maxn], *Null, *Root;
queue<Node*> q; Node* newNode(int v) {
Node* t = q.front(); q.pop();
t->s = 1;
t->v = v;
t->r = rand();
t->ch[0] = t->ch[1] = Null;
return t;
} void InitTreap() {
for(int i = 1; i < maxn; i++)
q.push(pool + i);
Root = Null = pool;
Null->sum = 0;
Null->s = 0;
Null->ch[0] = Null->ch[1] = Null;
} void Rotate(Node*&t, int d) {
Node* o = t->ch[d ^ 1];
t->ch[d ^ 1] = o->ch[d];
o->ch[d] = t;
t->upd(); o->upd();
t = o;
} void Insert(Node*&t, int v) {
// printf("%d\n", v);
if(t == Null) {
t = newNode(v);
} else {
int d = (v > t->v);
Insert(t->ch[d], v);
if(t->ch[d]->r > t->r)
Rotate(t, d ^ 1);
}
t->upd();
} void Delete(Node*&t, int v) {
int d = (t->v == v ? -1 : (v > t->v));
if(!~d) {
if(t->ch[0] != Null && t->ch[1] != Null) {
int _d = (t->ch[0]->r > t->ch[1]->r);
Rotate(t, _d);
Delete(t->ch[_d], v);
} else {
q.push(t);
t = (t->ch[0] == Null ? t->ch[1] : t->ch[0]);
}
} else
Delete(t->ch[d], v);
if(t != Null)
t->upd();
} ll ans = 0, sum = 0;
int sz = 0, N, Q; void update(int v, bool typ) {
int _sz = 0;
ll _sum = 0;
for(Node* t = Root; t != Null; ) {
if(t->v <= v)
_sz += t->ch[0]->s + 1, _sum += t->ch[0]->sum + t->v, t = t->ch[1];
else
t = t->ch[0];
} if(typ) {
// printf("%d %d %d %lld %lld\n", v, sz, _sz, sum, _sum);
ans += ll(v) * _sz - _sum;
ans += sum - _sum - ll(v) * (sz - _sz);
sz++, sum += v;
} else {
ans -= ll(_sz) * v - _sum;
ans -= sum - _sum - ll(v) * (sz - _sz);
sz--, sum -= v;
}
} bool Find(Node* t, int v) {
if(t == Null) return false;
if(t->v == v) return true;
return v < t->v ? Find(t->ch[0], v) : Find(t->ch[1], v);
} int main() {
// freopen("test.in", "r", stdin); InitTreap(); N = read(); Q = read();
for(int i = 0; i < N; i++) {
int v = read();
update(v, 1);
Insert(Root, v);
}
while(Q--) {
int opt = read();
if(opt == 3)
printf("%lld\n", ans);
else {
int v = read();
if(opt == 1) {
update(v, 1);
Insert(Root, v);
} else {
if(!Find(Root, v)) {
puts("-1"); continue;
}
update(v, 0);
Delete(Root, v);
}
}
} return 0;
}
C.找朋友
题目大意:给两个长度为N的数列A、B,一个有m个元素的集合K.Q个询问[l,r]内满足|Bi-Bj|∈K 的最大Ai+Aj.N,Q≤100000,M≤10
一开始不太会做...用莫队的话是O(M*N^1.5)..会TLE..因为至多有M*N对满足题意的数对,我们可以直接考虑他们对答案的贡献...那么离线将询问排序然后线段树维护就可以了,时间复杂度O(MNlogN)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype> using namespace std; const int maxn = 100009; int read() {
char c = getchar();
int ret = 0;
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
} int N, Q, M, A[maxn], B[maxn], _B[maxn], K[maxn], ans[maxn]; struct QUERY { int l, r, p; void Read(int x) {
l = read(); r = read(); p = x;
} bool operator < (const QUERY &o) const {
return l < o.l;
} } q[maxn]; void Init() {
memset(_B, -1, sizeof _B);
N = read(); Q = read(); M = read();
for(int i = 1; i <= N; i++) A[i] = read();
for(int i = 1; i <= N; i++) _B[B[i] = read()] = i;
for(int i = 0; i < M; i++) K[i] = read();
for(int i = 0; i < Q; i++) q[i].Read(i);
sort(q, q + Q);
// for(int i = 0; i < Q; i++)
// printf("[ %d , %d ] %d\n", q[i].l, q[i].r, q[i].p);
} int L, R, V; struct Node { Node *l, *r;
int v; Node() : v(0) {
l = r = NULL;
} void upd() {
if(l)
v = max(l->v, r->v);
} } pool[maxn << 1], *pt = pool, *Root; void Build(Node* t, int l, int r) {
if(l == r)
return;
int m = (l + r) >> 1;
Build(t->l = pt++, l, m);
Build(t->r = pt++, m + 1, r);
} void Modify(Node* t, int l, int r) {
if(l == r)
t->v = max(t->v, V);
else {
int m = (l + r) >> 1;
R <= m ? Modify(t->l, l, m) : Modify(t->r, m + 1, r);
t->upd();
}
} int Query(Node* t,int l, int r) {
if(L <= l && r <= R)
return t->v;
int m = (l + r) >> 1;
return max(L <= m ? Query(t->l, l, m) : 0, m < R ? Query(t->r, m + 1, r) : 0);
} int main() {
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout); Init(); Build(Root = pt++, 1, N); int p = Q - 1;
for(L = N; L; L--) {
// printf("%d\n", L);
int &v = B[L];
for(int j = 0; j < M; j++) {
if(v - K[j] >= 1 && ~_B[v - K[j]] && _B[v - K[j]] > L) {
V = A[L] + A[R = _B[v - K[j]]];
// printf("%d\n", V);
Modify(Root, 1, N);
}
if(v + K[j] <= N && ~_B[v + K[j]] && _B[v + K[j]] > L) {
V = A[L] + A[R = _B[v + K[j]]];
Modify(Root, 1, N);
}
}
// printf("%d\n", p);
while(~p && q[p].l == L) {
R = q[p].r;
// printf("p = %d %d \n", p, Query(Root, 1, N));
ans[q[p--].p] = Query(Root, 1, N);
}
// printf("%d\n", L);
if(p < 0) break;
} for(int i = 0; i < Q; i++)
printf("%d\n", ans[i]); return 0;
}
D,E,F都不会写...D题完全没什么思路.E题感觉可以搞但是因为要输出1~N的就不会了,O(N^2)妥妥的TLE啊...
F题推不出来...
这是E题..假如你会的话请评论...
膜11个AK..
51NOD 算法马拉松8的更多相关文章
- 51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)
题目链接 51nod 算法马拉松 34 Problem D 在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可. 首先考虑任意一个点对$(i, j)$ ...
- 随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3
先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率 假 ...
- 51Nod 算法马拉松21(迎新年)
这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过 ...
- 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛
OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...
- 51Nod 算法马拉松23 开黑记
惨啊……虽然开了半天黑,但是还是被dalao们踩了…… 第二次开黑,还是被卡在rank20了,我好菜啊……= = 写一写比赛经过吧…… 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是 ...
- 51Nod 算法马拉松22 开黑记
这是一场惨烈的开黑大战,始于全机房开黑指望刷进rank前十拿钱的壮志,终于被各路神犇怒踩成rank20,差点200点头盾不保的落魄,想起将近一年前ad和zcg等学长挤进rank10的壮举,不由得唏嘘, ...
- 51nod算法马拉松 contest7
A题 链接:http://www.51nod.com/contest/problem.html#!problemId=1417 推荐链接:http://blog.csdn.net/a837199685 ...
- 51nod算法马拉松15
智力彻底没有了...看来再也拿不到奖金了QAQ... A B君的游戏 因为数据是9B1L,所以我们可以hash试一下数据... #include<cstdio> #include<c ...
- 51nod 算法马拉松18 B 非010串 矩阵快速幂
非010串 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 如果一个01字符串满足不存在010这样的子串,那么称它为非010串. 求长度为n的非010串的个数.(对1e9+7取模) ...
随机推荐
- EOF 空格问题
mysql -u $USER -p${PASSWORD} $DATABASE << EOF >/tmp/dd-$$ 2>/tmp/ddd-$$select *from $TAB ...
- Largest Submatrix(动态规划)
Largest Submatrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- c++ 回调类成员函数实现
实现类成员函数的回调,并非静态函数:区分之 #ifndef __CALLBACK_PROXY_H_ #define __CALLBACK_PROXY_H_ template <typename ...
- 如何查看npm配置?
npm config list //查看基本配置 npm config list -l //查看所有配置 npm本地安装与全局安装有什么区别? npm install grunt // 本地安装,则是 ...
- JavaScript之<script>标签简介
向html页面中插入JavaScrpt的主要方法,就是使用<script>元素,下面是Html 4.01为<script>定义的6个属性. 1.async:可选表示应该立即下载 ...
- visio 2013 破解工具 - KMSpico
背景:环境是 win7, 64 bit装了 visio 2013 , 可以却不能用它来画图,在网上找了一些破解工具,大都不能解决问题.网上不靠谱的广告型文章太多了,比较头痛. 所幸,终于找到正确的破解 ...
- Infragistics的介绍以及在ASP.net中使用的总结
Infragistics系列控件是一套很好,很强大的控件,.感觉很好..现在自己做项目也用..却发现网上没有一套中文的教程,中文资料都很少..在这里就把自己的研究心得写下来... 首先安装,一步一步装 ...
- openwrt看IP流量
可以利用iptable来实现的,看附件的脚本. 把他放到路由器里面,然后运行. #!/bin/sh echo "Collecting data..." echo "&qu ...
- pyhon MySQLdb查询出来的数据设置为字典类型
import MySQLdbimport MySQLdb.cursors cxn=MySQLdb.Connect(host='localhost',user='root',passwd='1234', ...
- Apache与Nginx优缺点比较
本文来源:收集.整理自互联网 1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache ...