太神仙了这题。。。


原来的地面上升,可以倒着操作(时光倒流),转化为地面沉降,最后的答案就是每个点的深度。

下面的1,2操作均定义为向下沉降(与原题意的变换相反);

首先这个题目只会操作前缀和后缀,并且只会把前缀中的数(纵坐标)变小(2操作),后缀中的数(横坐标)变大(1操作),所以具有单调性,可以进行二分。(括号中含义的解释见下)

先把整个坐标系旋转$45$度(逆时针为例),操作1即纵坐标$y>=xi$的点都会往右走$2*l$,横坐标$+2*l$,纵坐标不变,由于有单调性,只会操作后缀;操作2即横坐标$x<=xi$的点都会往下走$2*l$,纵坐标$-2*l$,横坐标不变,由于有单调性,只会操作前缀。

所以二分一下实际坐标就好了。。注意最后计算深度是$(x-y)/2$

我的这种二分需要维护一个$mx$区间最大值,二分时看一眼左右子树的$mx$,然后决定向哪一棵子树递归。

#include<cstdio>
#include<iostream>
#define ls (tr<<1)
#define rs (tr<<1|1)
#define ll long long
#define R register ll
const int N=,Inf=0x3f3f3f3f;
using namespace std;
char B[<<],*S=B,*T=B,ch;
#define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m;
struct node {int x,d,l;}q[N];
ll MX[][N<<],TG[][N<<];
#define mx MX[c]
#define tg TG[c]
inline void build(int c,int tr,int l,int r) {
if(l==r) {mx[tr]=l; return ;} R md=l+r>>;
build(c,ls,l,md),build(c,rs,md+,r); mx[tr]=max(mx[ls],mx[rs]);
}
inline void spread(int c,int tr) { if(!tg[tr]) return ;
tg[ls]+=tg[tr],tg[rs]+=tg[tr],mx[ls]+=tg[tr],mx[rs]+=tg[tr]; tg[tr]=;
} ll pos;
inline void fx(int tr,int l,int r,int k) {
if(l==r) {if(MX[][tr]<=k) pos=max(pos,(ll)l); return ;} spread(,tr); R md=l+r>>;
if(MX[][ls]<=k) pos=max(pos,md),fx(rs,md+,r,k); else fx(ls,l,md,k);
}
inline void fy(int tr,int l,int r,int k) {
if(l==r) {if(MX[][tr]>k) pos=min(pos,(ll)l); return ;} spread(,tr); R md=l+r>>;
if(MX[][ls]<=k) fy(rs,md+,r,k); else fy(ls,l,md,k);
}
inline void add(int c,int tr,int l,int r,int LL,int RR,int d) {
if(LL<=l&&r<=RR) {mx[tr]+=d,tg[tr]+=d; return ;} spread(c,tr); R md=l+r>>;
if(LL<=md) add(c,ls,l,md,LL,RR,d); if(RR>md) add(c,rs,md+,r,LL,RR,d); mx[tr]=max(mx[ls],mx[rs]);
} ll p[][N];
inline void calc(int c,int tr,int l,int r) {
if(l==r) {p[c][l]=mx[tr]; return ;} spread(c,tr);
R md=l+r>>; calc(c,ls,l,md),calc(c,rs,md+,r);
}
signed main() { freopen("geologic.in","r",stdin); freopen("geologic.out","w",stdout);
n=g(),m=g(); for(R i=;i<=m;++i) q[i].x=g(),q[i].d=g(),q[i].l=g();
build(,,,n),build(,,,n); for(R i=m;i>=;--i) {
if(q[i].d==) {
pos=; fx(,,n,q[i].x);
if(pos) add(,,,n,,pos,-*q[i].l);
} else {
pos=Inf; fy(,,n,q[i].x);
if(pos!=Inf) add(,,,n,pos,n,*q[i].l);
} //cerr<<pos<<endl;
} calc(,,,n),calc(,,,n);
for(R i=,ans;i<=n;++i) ans=(p[][i]-p[][i])/,printf("%lld\n",ans);
}

这还有一个不旋转坐标的,具体的就是类似直接模拟,但是难度在如何二分位置;

想一想发现:这不是直线方程么。。。

所以还是分别维护横纵坐标,但是二分条件改成$y>=x-xi$即$x-y<=xi$或$y>=-x+xi$即$x+y>=xi$;

#include<cstdio>
#include<iostream>
#define ll long long
#define R register ll
const int M=;
char B[<<],*S=B,*T=B;
#define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
using namespace std;
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
} ll x[M],y[M],ans[M];
inline int fx(ll d) { R pos=,t;
for(R i=;~i;--i) if((t=x[pos+(<<i)]-y[pos+(<<i)])<=d) pos+=(<<i),d-=t; return pos;
}
inline int fy(ll d) { R pos=,t;
for(R i=;~i;--i) if((t=x[pos+(<<i)]+y[pos+(<<i)])<=d) pos+=(<<i),d-=t; return pos;
} int n,m;
inline void add(int pos,int incx,int incy) {for(;pos<M;pos+=pos&-pos) x[pos]+=incx,y[pos]+=incy;}
struct node {int x,d,l;} q[M];
signed main() { freopen("geologic.in","r",stdin); freopen("geologic.out","w",stdout);
n=g(),m=g(); for(R i=;i<=n;++i) add(i,,);
for(R i=;i<=m;++i) q[i].x=g(),q[i].d=g(),q[i].l=g();
for(R i=m;i;--i) if(q[i].d==) {
R pos=fx(q[i].x); if(pos) add(,-q[i].l,-q[i].l),add(pos+,q[i].l,q[i].l);
} else { R pos=fy(q[i].x); if(pos<n) add(pos+,q[i].l,-q[i].l);}
for(R i=;i<=n;++i) {
ans[i]=ans[i-(i&-i)]+y[i];
printf("%lld\n",-ans[i]);
}
}

2019.06.01 June

Luogu P5103 「JOI 2016 Final」断层 树状数组or线段树+脑子的更多相关文章

  1. 「JOI 2016 Final」断层

    嘟嘟嘟 今天我们模拟考这题,出的是T3.实在是没想出来,就搞了个20分暴力(还WA了几发). 这题关键在于逆向思维,就是考虑最后的\(n\)的个点刚开始在哪儿,这样就减少了很多需要维护的东西. 这就让 ...

  2. LOJ#2343. 「JOI 2016 Final」集邮比赛 2

    题目地址 https://loj.ac/problem/2343 题解 首先处理出\(f[i]\)表示以当前位置开头(J,O,I)的合法方案数.这个显然可以\(O(n)\)处理出来.然后考虑在每个位置 ...

  3. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

  4. LOJ#2351. 「JOI 2018 Final」毒蛇越狱

    LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做. 观察到\(min(|1|,| ...

  5. 「JOI 2017 Final」JOIOI 王国

    「JOI 2017 Final」JOIOI 王国 题目描述 题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」 JOIOI 王国是一个 H ...

  6. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  7. 【题解】LOJ2759. 「JOI 2014 Final」飞天鼠(最短路)

    [题解]LOJ2759. 「JOI 2014 Final」飞天鼠(最短路) 考虑最终答案的构成,一定是由很多飞行+一些上升+一些下降构成. 由于在任何一个点上升或者下降代价是一样的,所以: 对于上升操 ...

  8. 「JOI 2014 Final」飞天鼠

    「JOI 2014 Final」飞天鼠 显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0. 到达一个点有两种情况:到达高度为0和不为0. 对于高度不为0的情况,显然花费的时间越少高度越高 ...

  9. 「JOI 2015 Final」城墙

    「JOI 2015 Final」城墙 复杂度默认\(m=n\) 暴力 对于点\((i,j)\),记录\(ld[i][j]=min(向下延伸的长度,向右延伸的长度)\),\(rd[i][j]=min(向 ...

随机推荐

  1. 洛谷【P1142】轰炸

    我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:https://www.luogu.org/problemnew/show/P ...

  2. 查看,修改,上传monmap命令

    标签(空格分隔): ceph,ceph运维,monmap 查看集群monmap命令 从集群获取monmap: # ceph mon getmap -o monmap 查看上一步下载的monmap: # ...

  3. Sql server 备份及还原

    --最常用的几种备份方法: --数据备份----------------------- --数据库级:完整数据库备份 差异数据库备份 --文件级: 完整文件备份 差异文件备份 --日志备份------ ...

  4. linux命令-rpm安装和卸载

    软件包 先查看一下rpm包 [root@wangshaojun Packages]# mount /dev/cdrom /mnt/////挂载[root@wangshaojun Packages]# ...

  5. 关于UI性能优化

    1.使用已经有的VIEW,而不是每次都去新生成一个 2.创建自定义类来进行组件和数据的缓存,在下一次调用的时候直接从FLAG中取出 3.分页,预加载 使用VIEWSTUB进行调用时加载 VIEWSTU ...

  6. 9、samtool view

    参考:https://www.sogou.com/link?url=DOb0bgH2eKh1ibpaMGjuy6YnbQPc3cuKbWqIy1k6SBFomuBEhdSpHkUUZED5fr2OTk ...

  7. 我的windows软件

    1.360安全卫士 http://www.360.cn/ 装好系统后用它来卸载预装软件,杀毒,关闭开机启动项和清理垃圾 2.QQ http://im.qq.com/download/ 手机和电脑通信 ...

  8. 在Ionic Framework 退出APP

    使用以下代码: ionic.Platform.exitApp(); 在控制器中增加: $scope.Quit = function(){ ionic.Platform.exitApp(); }

  9. js中将字符串转为JSON的三种方式

    1.eval方式解析,恐怕这是最早的解析方式了.如下: function strToJson(str){ var json = eval('(' + str + ')'); return json; ...

  10. Spring-boot 项目中使用 jackson 遇到的一个问题

    jackson介绍 java代码中实现序列化和反序列化的工具类 jackson使用Demo https://github.com/Naylor55/JavaDebrisCode/tree/branch ...