洛谷p3801:红色的幻想乡
Posted a799091501
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷p3801:红色的幻想乡相关的知识,希望对你有一定的参考价值。
初见完全没有思路.....感觉像是线段树 但二维感觉完全不可做嘛
于是只能去看了看题解 然而还是疯狂爆零+WA..
和yycc神犇调了两三个小时才调出来...
——————以下个人理解
考虑到每次的修改都是对整行和整列进行操作
可以把每行缩成一个点 这样修改就相当于对这个点进行单点修改
同理也把每列缩成一个点
那么对于每一次修改操作 我们只需要将这个点的横坐标与纵坐标进行修改即可
也就是维护两棵线段树,分别表示行和列
显然可以看出对于图里的每一个点,只有有红雾和没红雾两种状态,并且又说两次红雾会抵消
于是每一次修改就相当于做一次取反操作 还需要支持的另一个操作就是朴素的区间求和
但这显然不是正解 因为每一次操作时实际对于蕾咪所在的那个点是完全没有影响的 而在我们的修改时没有考虑到这一点
似乎没有什么好办法?......好像标记的话会退化回O(Nlogn)....
当然是选择容斥它辣.....但是蒟蒻博主也不会...我太弱啦!
又请教了一下yycc神犇
画图可知 a条横着的直线与b条竖着的直线的交点数为a*b
而每一个交点我们在横竖修改的时候都分别对他对多标记了一次
所以只需在结果上减去一个ansx*ansy*2就是答案了
码农题
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #include<limits.h> #include<ctime> #define N 1000001 typedef long long ll; const int inf=0x3fffffff; const int maxn=2017; using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch>\'9\'|ch<\'0\') { if(ch==\'-\') f=-1; ch=getchar(); } while(ch<=\'9\'&&ch>=\'0\') { x=(x<<3)+(x<<1)+ch-\'0\'; ch=getchar(); } return f*x; } struct tsdl{ ll w; }xtr[N],ytr[N]; void updatex(ll l,ll r,ll pos,ll x) { if(l==r) { xtr[pos].w^=1; return; } ll mid=l+r>>1; if(mid>=x)updatex(l,mid,pos<<1,x); else updatex(mid+1,r,pos<<1|1,x); xtr[pos].w=xtr[pos<<1].w+xtr[pos<<1|1].w; } void updatey(ll l,ll r,ll pos,ll x) { if(l==r) { ytr[pos].w^=1; return; } ll mid=l+r>>1; if(mid>=x)updatey(l,mid,pos<<1,x); else updatey(mid+1,r,pos<<1|1,x); ytr[pos].w=ytr[pos<<1].w+ytr[pos<<1|1].w; } ll queryx(ll l,ll r,ll a,ll b,ll pos) { if(l>=a&&r<=b) { return xtr[pos].w; } ll ans=0; ll mid=l+r>>1; if(mid>=a)ans+=queryx(l,mid,a,b,pos<<1); if(mid<b)ans+=queryx(mid+1,r,a,b,pos<<1|1); return ans; } ll queryy(ll l,ll r,ll a,ll b,ll pos) { if(l>=a&&r<=b) { return ytr[pos].w; } ll ans=0; ll mid=l+r>>1; if(mid>=a)ans+=queryy(l,mid,a,b,pos<<1); if(mid<b)ans+=queryy(mid+1,r,a,b,pos<<1|1); return ans; } int main() { ll n=read(),m=read(),k=read(); while(k--) { ll opt=read(); switch(opt) { case 1: { ll x=read(),y=read(); updatex(1,n,1,x); updatey(1,m,1,y); break; } case 2: { ll ans=0; ll xa=read(),ya=read(),xb=read(),yb=read(); ll ansx=queryx(1,n,xa,xb,1); ll ansy=queryy(1,m,ya,yb,1); cout<<ansy*(xb-xa+1)+ansx*(yb-ya+1)-ansx*ansy*2<<endl; } } } }
以上是关于洛谷p3801:红色的幻想乡的主要内容,如果未能解决你的问题,请参考以下文章