【50.40%】【BZOJ 4553】[Tjoi2016&Heoi2016]序列
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 371 Solved: 187
[Submit][Status][Discuss]
Description
佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值
Input
输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的
Output
输出一个整数,表示对应的答案
Sample Input
1 2 3
1 2
2 3
2 1
3 4
Sample Output
【题解】
题的意思是说进行一次变化操作之后,变成新的序列,然后序列又变回原状,然后再进行下一个变换,变成新状态->又变回原状。。
然后在这几次变化之后形成的所有序列。找一个下标a1,a2..at,在这所有形成的序列中都都要满足a[a1]<=a[a2]<=...<=a[at].
求t的最大值。
设下标为i的数字最大会变成r[i],最小会变成l[i].然后原数字是v[i]
则第j个元素能接在第i个元素后面加长以第i个元素为结尾的最长上升序列的长度的条件是r[i] <= a[j]且a[i] <= l[j].前者是第i个元素发生变化,后者是第j个元素发生变化所要满足的情况。
还是提醒一句。进行一次操作过后。马上序列又变回原状。而且每次操作只会改变一个对应下标的数字。
则f[j] = max(f[i])+1;(i∈1..j-1;a[i] <= l[j]且r[i] <= a[j])
但是n=10W.
这种做法是n^2的。。
于是做一下改进。
我们在转移的时候实际上就是在找某些范围里面的点。
我们设点的坐标为(a[p],r[q]);(抽象)
那我们对第i个数字进行DP的时候
实际上就是要在某种数据结构中找坐标范围为(0..l[i],0..a[i])的点里面f值最大的。
转移完之后就获得了f[i]的值。
然后再把第i个点的f[i]加到这种数据结构里面就好了。
这种问题可以用kdtree来实现。
n太巨大。需要不时重建kdtree。不然插入操作会让kdtree退化。
经过试验每6000次重建一次效果最好。5000也能通过。
4000、10000这些周期则会T
具体看代码
【代码】
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- const int MAXN = 109000;
- int n, m,root,ans = 0,now;
- struct point
- {
- int l, r,v;
- };
- struct node
- {
- int ma_x[2], mi_n[2], l, r, dot,f, max,d[2];
- };
- point shuju[MAXN];
- node t[MAXN],op;
- int totn = 0,mi_n[2],ma_x[2];
- void input_data()
- {
- scanf("%d%d", &n, &m);
- for (int i = 1; i <= n; i++)
- {
- scanf("%d", &shuju[i].v);
- shuju[i].l = shuju[i].r = shuju[i].v;
- }
- for (int i = 1; i <= m; i++)
- {
- int index, num;
- scanf("%d%d", &index, &num);
- shuju[index].l = min(shuju[index].l, num);
- shuju[index].r = max(shuju[index].r, num);
- }
- }
- void up_data(int rt)
- {
- int l = t[rt].l, r = t[rt].r;
- for (int i = 0; i <= 1; i++)
- {
- if (l)
- {
- t[rt].ma_x[i] = max(t[rt].ma_x[i], t[l].ma_x[i]);
- t[rt].mi_n[i] = min(t[rt].mi_n[i], t[l].mi_n[i]);
- if (t[l].max > t[rt].max)
- {
- t[rt].max = t[l].max;
- //t[rt].dot = t[l].dot;
- }
- }
- if (r)
- {
- t[rt].ma_x[i] = max(t[rt].ma_x[i], t[r].ma_x[i]);
- t[rt].mi_n[i] = min(t[rt].mi_n[i], t[r].mi_n[i]);
- if (t[r].max > t[rt].max)
- {
- t[rt].max = t[r].max;
- //t[rt].dot = t[r].dot;
- }
- }
- }
- }
- void insert(int &rt, int fx)//插入节点
- {
- if (!rt)
- {
- rt = ++totn;
- t[rt] = op;
- t[rt].max = t[rt].f;
- t[rt].l = t[rt].r = 0;
- //t[rt].dot = rt;
- for (int i = 0; i <= 1; i++)
- t[rt].ma_x[i] = t[rt].mi_n[i] = t[rt].d[i];
- return;
- }
- else
- {
- if (op.d[fx] < t[rt].d[fx])
- insert(t[rt].l, 1 - fx);
- else
- insert(t[rt].r, 1 - fx);
- }
- up_data(rt);
- }
- int query(int rt)
- {
- if (!rt)
- return 0;
- if (mi_n[0] <= t[rt].mi_n[0] && t[rt].ma_x[0] <= ma_x[0]
- && mi_n[1] <= t[rt].mi_n[1] && t[rt].ma_x[1] <= ma_x[1])
- return t[rt].max; //整棵子树里面的点都在所求范围内
- if (t[rt].ma_x[0] < mi_n[0] || t[rt].mi_n[0] > ma_x[0] || t[rt].ma_x[1] < mi_n[1]
- || t[rt].mi_n[1] > ma_x[1])//都不在范围内
- return 0;
- int big = 0;
- if (mi_n[0] <= t[rt].d[0] && t[rt].d[0] <= ma_x[0] &&
- mi_n[1] <= t[rt].d[1] && t[rt].d[1] <= ma_x[1])
- big = max(big, t[rt].f);//当前这个节点在范围内。
- int l = t[rt].l, r = t[rt].r;
- if (l)
- big = max(big, query(l));
- if (r)
- big = max(big, query(r));
- return big;
- }
- bool cmp(node a, node b)
- {
- return a.d[now] < b.d[now];
- }
- int rebuild(int begin, int end, int fx)
- {
- int m = (begin + end) >> 1;
- now = fx;
- nth_element(t + begin, t + m, t + end + 1, cmp);
- for (int i = 0; i <= 1; i++)
- t[m].ma_x[i] = t[m].mi_n[i] = t[m].d[i];
- t[m].max = t[m].f;
- if (begin < m)
- t[m].l = rebuild(begin, m - 1, 1 - fx);
- else
- t[m].l = 0;//不能省,要重建的
- if (m < end)
- t[m].r = rebuild(m + 1, end, 1 - fx);
- else
- t[m].r = 0;
- up_data(m);
- return m;
- }
- void get_ans()
- {
- //j < i r[j] <= v[i]
- //j < i v[j] <= l[i]
- op.d[0] = shuju[1].r;
- op.d[1] = shuju[1].v;
- op.f = 1;
- insert(root,0);
- ans = 1;
- for (int i = 2;i <= n;i++)
- {
- if ((i % 6000) == 0)
- {
- root = rebuild(1, totn,0);
- }
- mi_n[0] = 0; ma_x[0] = shuju[i].v;
- mi_n[1] = 0; ma_x[1] = shuju[i].l;
- int temp = query(root);
- op.d[0] = shuju[i].r;
- op.d[1] = shuju[i].v;
- op.f = 1;
- if (temp)
- {
- if (temp + 1 > ans)
- ans = temp + 1;
- op.f = temp + 1;
- }
- insert(root, 0);
- }
- }
- void output_ans()
- {
- printf("%d\n", ans);
- }
- int main()
- {
- //freopen("F:\\rush.txt", "r", stdin);
- input_data();
- get_ans();
- output_ans();
- return 0;
- }
【50.40%】【BZOJ 4553】[Tjoi2016&Heoi2016]序列的更多相关文章
- BZOJ 4553 Tjoi2016&Heoi2016 序列
Tjoi2016&Heoi2016序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值 可能会变化,但同一个时刻最 ...
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...
- 4553: [Tjoi2016&Heoi2016]序列
4553: [Tjoi2016&Heoi2016]序列 链接 分析: 注意所有m此操作中,只会发生一个,于是考虑dp.dp[i]=dp[j]+1,j<i,a[j]<=L[i],R[ ...
- [BZOJ4553][TJOI2016&&HEOI2016]序列(CDQ分治)
4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 554[Su ...
- [BZOJ4553][Tjoi2016&Heoi2016]序列 cdp分治+dp
4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 260 Solved: 133[Sub ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- bzoj4553 [Tjoi2016&Heoi2016]序列 树状数组(区间最大值)+cqd
[Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1006 Solved: 464[Submit][ ...
- BZOJ 4552: [Tjoi2016&Heoi2016]排序
4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 579 Solved: 322[Sub ...
- BZOJ 4554: [Tjoi2016&Heoi2016]游戏 二分图匹配
4554: [Tjoi2016&Heoi2016]游戏 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4554 Descripti ...
- bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化
[Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 679 Solved: 534[Submit][S ...
随机推荐
- iOS 9适配
iOS 9系统策略更新,请开发者注意升级 近期苹果公司iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查 ...
- python 子类中定义init方法
- PHPCMS快速建站系列
模板标签 {pc:content action="position" posid="2" order="id DESC" num=&qu ...
- 洛谷P2062 分队问题
这是一道普及/提高- 然后你懂的,贪心扫一遍就可以了. 不懂提交人数那么少. //Serene #include<algorithm> #include<iostream> ...
- 【JZOJ4833】【NOIP2016提高A组集训第3场10.31】Mahjong
题目描述 解法 搜索. 代码 #include<stdio.h> #include<iostream> #include<string.h> #include< ...
- mysql设置text字段为not null,并且没有默认值,插入报错:doesn't have a default value
一.问题描述 在往数据库写入数据的时候,报错: '字段名' doesn't have a default value 本来这个错误是经常见到的,无非就是字段没有设置默认值造成的.奇怪的是,我这边报错的 ...
- 开发者说:Sentinel 流控功能在 SpringMVC/SpringBoot 上的实践
从用户的视角来感受一个开源项目的成长,是我们推出「开发者说」专栏的初衷,即在开发者进行开源项目选型时,提供更为立体的项目信息.专栏所有内容均来自作者原创/投稿,本文是「开发者说」的第6篇,作者 Jas ...
- 1月房地产企业销售TOP100出炉 万科重回第一
1月房地产企业销售TOP100出炉 万科重回第一 2017-02-05 07:40:32 来源:腾讯新闻 责任编辑: [摘要]TOP100房企1月的销售金额合计4311.8亿元,销售面积合计3648. ...
- BKDRhash
哈希: 字符串(数字同理): 例如有100000个字符串,现在要插入一些字符串,插入前比较是否已经存在避免含有重复数据 用暴力计较的话会比较慢,在某字符串插入时,最好的情况是在第一个位置就遇见该字符 ...
- selenium webdriver学习(九)------------如何操作cookies(转)
selenium webdriver学习(九)------------如何操作cookies 博客分类: Selenium-webdriver Web 测试中我们经常会接触到Cookies,一个C ...