BZOJ3847: ZCC loves march

31 篇文章 0 订阅
9 篇文章 0 订阅

每个点如果不考虑被分裂出去,他至多只会被合并一次,维护两个set,每次合并可以暴力找出这一行/列的所有点,并查集资瓷一下合并成一个点,每次分裂可以直接新建一个点代表这个分出去的点

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e18+1
using namespace std;

const int dx[]={-1,0,1,0};
const int dy[]={0,1,0,-1};
const ll Mod = 1e9+7;
ll sqr(ll x){x=x%Mod;return x*x%Mod;}
const int maxn = 410000;

char to[1100];

int n,m;
int tru[maxn];
int num[maxn],fa[maxn];
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}

struct nodex
{
    ll x,y;int i; 
    friend inline bool operator <(const nodex aa,const nodex b)
    {
        return aa.x==b.x?aa.y<b.y:aa.x<b.x;
    }
}a[maxn];
multiset<nodex>Sx;
multiset<nodex>::iterator itx,itx2;
struct nodey
{
    ll x,y;int i;
    friend inline bool operator <(const nodey aa,const nodey b)
    {
        return aa.y==b.y?aa.x<b.x:aa.y<b.y;
    }
};
multiset<nodey>Sy;
multiset<nodey>::iterator ity,ity2;

int lastans;
char str[110];

int main()
{
    to['U']=0,to['R']=1,to['D']=2,to['L']=3;

    scanf("%d%*lld",&n);
    for(int i=1;i<=n;i++)
    {
        ll x,y; scanf("%lld%lld",&x,&y);
        a[i].x=x; a[i].y=y; a[i].i=i; tru[i]=i;
        num[i]=1,fa[i]=i;
        Sx.insert((nodex){x,y,i});
        Sy.insert((nodey){x,y,i});
    }

    scanf("%d",&m);
    while(m--)
    {
        scanf("%s",str);
        if(str[0]=='Q')
        {
            int x; scanf("%d",&x); x=tru[x^lastans]; lastans=0;
            int ff=findfa(x);
            a[++n]=a[ff]; a[n].i=n;
            num[n]=num[ff]; num[ff]=0; fa[ff]=fa[n]=n;

            nodex tmpx=(nodex){a[ff].x-1,inf};
            itx=Sx.lower_bound(tmpx);
            while(itx!=Sx.end())
            {
                itx2=itx; itx2++;
                if((*itx).x!=a[ff].x) break;
                int ii=(*itx).i;
                if(findfa(ii)==ii)
                {
                    fa[ii]=n; num[n]+=num[ii];
                    (lastans+=sqr((*itx).y-a[ff].y)*num[ii]%Mod)%=Mod;
                    num[ii]=0;
                }
                Sx.erase(itx); itx=itx2;
            }

            nodey tmpy=(nodey){inf,a[ff].y-1};
            ity=Sy.lower_bound(tmpy);
            while(ity!=Sy.end())
            {
                ity2=ity; ity2++;
                if((*ity).y!=a[ff].y) break;
                int ii=(*ity).i;
                if(findfa(ii)==ii)
                {
                    fa[ii]=n; num[n]+=num[ii];
                    (lastans+=sqr((*ity).x-a[ff].x)*num[ii]%Mod)%=Mod;
                    num[ii]=0;
                }
                Sy.erase(ity); ity=ity2;
            }
            Sx.insert(a[n]);
            Sy.insert((nodey){a[n].x,a[n].y,a[n].i});

            printf("%d\n",lastans);
        }
        else
        {
            int k=to[str[0]];
            int x; ll d; scanf("%d%lld",&x,&d);
            int y=x^lastans; x=tru[y];
            int ff=findfa(x);

            num[tru[y]=++n]=1,fa[n]=n;
            a[n]=a[ff]; a[n].i=n;
            a[n].x+=d*dx[k],a[n].y+=d*dy[k];
            Sx.insert(a[n]);
            Sy.insert((nodey){a[n].x,a[n].y,a[n].i});

            num[ff]--;
            if(!num[ff]) fa[ff]=0;
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值