【JZOJ】3196 物理
来源:互联网 发布:淘宝如何删除评论 编辑:程序博客网 时间:2024/05/18 01:46
Description
sg站在
空间限制 1G , 时间限制 5s
TuCao
这已经是非常好的题意了。。。。原题的信息更加confusing。例如只能朝一个方向传播题解和样例都没解释,声音频率能改也没有特别说明,导致我认为这题无比的复杂。
Preliminary Analysis
由于声音频率是可以改变的。
某个人传话给sg和sg传话他所花的时间可途径都是一样的,把对象反一下就好了。
我们只需要求sg传话给每个人的时间就好。
我们设
我们不难想到一个DP式
好的看懂题目这样的DP式就能有50分了= =
然而现场所有人都打了DFS因为以为可以往回走。
Solution
根据这个DP式我们可以知道对于位置
1.合法的位置
2.合法的
我们对于
那么怎么知道
我们不需要知道。
按照权值建一个线段树,每个决策
这样非常暴力,鉴于1G的空间我们不理了。
因为决策区间会移动,所以我们有必要删除队首元素。删除,也就是撤销,是普通线段树无法实现的功能。可持久化?或许可以?应该是不行的空间太大1G都不够用。
没错就是单调队列。
线段树套单调队列。
我们对于线段树的每个区间都开一个单调队列来维护一个该区间内单调递增的决策,一旦遇到位置不合法就弹出队首即可。每次插入都是
还有一个问题:
我们查询的区间不一定和之前完全相同,有交集就行。
如果我们只对线段树普通的赋值,完全覆盖才加入,这样就会丢失很多信息,简而言之就是错的。
我们对每个区间维护两个单调队列,Cover和Pass
Cover:完全覆盖该区间的决策的单调队列
Pass:经过该区间的决策的单调队列
也可以理解为
Cover:当前点的信息
Pass:该点及其子树的信息
这样我们查询的时候,除了查询是所有经过的区间的Cover,对于查询区间所完全覆盖的区间,我们把它们的Pass也算上。
这样一来,我们就可以得出正确答案了。
PS.数字范围很大请务必离散化
离散化能不用Hash就别用吧
一个区间在修改时,能更新Cover就没必要更新Pass了,因为Cover
常数较大,祝君好运。
此题的思想可以灵活运用于二维矩形赋值,关于维护二维的线段树等等。
#include<cstring>#include<cstdio>#include<algorithm>#include<vector>#include<map>using namespace std;const int N = 250010;map<int , int> Hash;struct Que{ int head,tail; vector<int> q;};struct Node{ int l,r; Que Cover , Pass;}tree[N * 20];struct Data{ int x,y,pos;}a[N];int F[N],n,l,mxt,myt,tot,inf,c[N * 2],P,Pos;void Relable(){ int td = 0 , id = 0; for (int i = 1 ; i <= n ; i ++) c[++ td] = a[i].x , c[++ td] = a[i].y; sort(c + 1 , c + 1 + td); for (int i = 1 ; i <= td ; i ++) if (!Hash[c[i]]) Hash[c[i]] = ++ id ; for (int i = 1 ; i <= n ; i ++) a[i].x = Hash[a[i].x] , a[i].y = Hash[a[i].y]; mxt = 1 , myt = id;}void Update(Que &t){ while (t.tail >= t.head && F[t.q[t.tail]] >= F[P]) t.tail --; ++ t.tail; if (t.tail < t.q.size()) t.q[t.tail] = P; else t.q.push_back(P);}void Mark(int now , int L , int R , int l , int r){ if (L == l && r == R) { Update(tree[now].Cover); // Update(tree[now].Pass , p); return; } Update(tree[now].Pass); int mid = (L + (long long)R) >> 1; if (r <= mid) { if (!tree[now].l) tree[now].l = ++ tot , tree[tot].Cover.tail = tree[tot].Pass.tail = -1; Mark(tree[now].l , L , mid , l , r); return ; } if (l > mid) { if (!tree[now].r) tree[now].r = ++ tot , tree[tot].Cover.tail = tree[tot].Pass.tail = -1; Mark(tree[now].r , mid + 1 , R , l , r); return ; } if (!tree[now].l) tree[now].l = ++ tot , tree[tot].Cover.tail = tree[tot].Pass.tail = -1; if (!tree[now].r) tree[now].r = ++ tot , tree[tot].Cover.tail = tree[tot].Pass.tail = -1; Mark(tree[now].l , L , mid , l , mid); Mark(tree[now].r , mid + 1 , R , mid + 1 , r); return;}inline int Gethead(Que &t){ while (t.head <= t.tail && a[t.q[t.head]].pos < Pos) t.head ++; if (t.head > t.tail) return inf; return F[t.q[t.head]];}int Query(int now , int L , int R , int l , int r){ int mid = (L + (long long)R) >> 1 , flag = inf;/* Gethead(tree[now].Cover); if (tree[now].Cover.head <= tree[now].Cover.tail) flag = F[tree[now].Cover.q[tree[now].Cover.head]];*/ flag = Gethead(tree[now].Cover); if (L == l && R == r) { /*Gethead(tree[now].Pass); if (tree[now].Pass.head <= tree[now].Pass.tail) flag = min(flag , F[tree[now].Pass.q[tree[now].Pass.head]]);*/ flag = min(flag , Gethead(tree[now].Pass)); return flag; } if (r <= mid) { if (!tree[now].l) return flag; return min(flag , Query(tree[now].l , L , mid , l , r)); } if (l > mid) { if (!tree[now].r) return flag; return min(flag , Query(tree[now].r , mid + 1 , R , l , r)); } if (tree[now].l) flag = min(flag , Query(tree[now].l , L , mid , l , mid)); if (tree[now].r) flag = min(flag , Query(tree[now].r , mid + 1 , R , mid + 1 , r)); return flag;}int main(){ freopen("2.in" , "r" , stdin);freopen("2.out" , "w" , stdout); scanf("%d%d" , &n , &l); mxt = 2000000010; tot = 1 , inf = N * 2; for (int i = 2 ; i <= n ; i ++) { scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].pos); mxt = min(a[i].x , mxt); myt = max(a[i].y , myt); } a[1].x = mxt , a[1].y = myt , a[1].pos = 0; Relable(); tree[1].Cover.tail = tree[1].Pass.tail = -1; P = 1 , Pos = 0; Mark(1 , mxt , myt , a[1].x , a[1].y); for (int i = 2 ; i <= n ; i ++) { Pos = a[i].pos - l; if (a[i].pos >= l) F[i] = Query(1 , mxt , myt , a[i].x , a[i].y); else F[i] = 0; //F[i] = Query(1 , mxt , myt , a[i].x , a[i].y); if (F[i] == inf) {F[i] = -1 ; continue;} F[i] ++;P = i; Mark(1 , mxt , myt , a[i].x , a[i].y); } for (int i = 2 ; i <= n ; i ++) printf("%d\n" , F[i]); return 0;}
- 【JZOJ】3196 物理
- 【JZOJ 4823】小W学物理
- JZOJ 4823. 【NOIP2016提高A组集训第1场10.29】小W学物理
- JZOJ 4823 【NOIP2016提高A组集训第1场10.29】小W学物理
- [JZOJ 3424] 粉刷匠 && [JZOJ 4254] 集体照
- [JZOJ 1280]最大匹配
- [JZOJ 1281]旅行
- [1282 JZOJ]资源勘探
- [JZOJ 1283]排序统计
- JZOJ NOIP2014模拟 8.12
- JZOJ NOIP2014模拟 8.13
- [JZOJ 1598]文件修复
- 【JZOJ 3111】单词查找
- 【JZOJ 3112】开会
- JZOJ 3463 军训
- 【JZOJ】3169 生产汽车
- 【JZOJ】3187 的士
- 【JZOJ】3188 找数
- WADL
- 面试笔记之二叉树篇
- LightOJ 题目1427 - Substring Frequency (II)(AC自动机)
- WebView使用详解
- 幸福人生在于正确选择
- 【JZOJ】3196 物理
- 欢迎使用CSDN-markdown编辑器
- Application源码分析
- Android之使用ThumbnailUtils类来获取视频第一帧缩略图
- Windows Azure HDInsight - 使用Hadoop 做数据分析
- ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)问题处理
- equals方法重写
- 文章标题
- php对比java之优劣(就像安卓和iOS一样,其实很难比高下)