• [BZOJ]4811: [Ynoi2017]由乃的OJ


     题解:   上一题的系列套路题  但是上一题 我们用n*log^3(n)水过了  这题6s明显是不可行的  需要优化一下复杂度  我们考虑线段树合并 维护每一位输入为0/1的时候输出 然后做区间合并  这样子平方转移依然是3个log的  我们想想二进制优化  让每一位对应unsigned long long每一二进制位然后把每次合并后的结果都用一个64位无符号整数存下来  这样就成2个log了  具体怎么合并 可以手推下

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=1e5+10;
    const double eps=1e-8;
    #define ll unsigned long long
    #define pii pair<ll,ll>
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    inline ll read()
    {
        ll ret=0;   char gc=getchar();
        while(gc<'0'||gc>'9') gc=getchar();
        while(gc>='0'&&gc<='9')   ret=ret*10+(gc-'0'),gc=getchar();
        return ret;
    }
    ll l0[MAXN<<2],l1[MAXN<<2],r0[MAXN<<2],r1[MAXN<<2];
    int opt[MAXN],n,m,k;
    ll a[MAXN],base;
    
    void up(int x){
        l0[x]=(l1[x<<1|1]&l0[x<<1])|((~l0[x<<1])&l0[x<<1|1]);
        l1[x]=(l1[x<<1]&l1[x<<1|1])|((~l1[x<<1])&l0[x<<1|1]);
        r0[x]=(r0[x<<1|1]&r1[x<<1])|((~r0[x<<1|1])&r0[x<<1]);
        r1[x]=(r1[x<<1|1]&r1[x<<1])|((~r1[x<<1|1])&r0[x<<1]);
    }
    
    void Opt1(int x,ll y){
        l0[x]=r0[x]=0;
        l1[x]=r1[x]=y;
    }
    
    void Opt2(int x,ll y){
        l0[x]=r0[x]=y;
        l1[x]=r1[x]=base;
    }
    
    void Opt3(int x,ll y){
        l0[x]=r0[x]=y;
        l1[x]=r1[x]=(base^y);
    }
    
    int tp[MAXN],p[MAXN],fp[MAXN],cnt;
    void built(int x,int l,int r){
        if(l==r){
    	if(opt[fp[l]]==1)Opt1(x,a[fp[l]]);
    	else if(opt[fp[l]]==2)Opt2(x,a[fp[l]]);
    	else Opt3(x,a[fp[l]]);
    	return ;
        }
        int mid=(l+r)>>1;
        built(x<<1,l,mid);
        built(x<<1|1,mid+1,r);
        up(x);
    }
    
    void update(int x,int l,int r,int t){
        if(l==r){
    	if(opt[fp[l]]==1)Opt1(x,a[fp[l]]);
    	else if(opt[fp[l]]==2)Opt2(x,a[fp[l]]);
    	else Opt3(x,a[fp[l]]);
    	return ;
        }
        int mid=(l+r)>>1;
        if(t<=mid)update(x<<1,l,mid,t);
        else update(x<<1|1,mid+1,r,t);
        up(x);
    }
    
    pii ans;
    void query1(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
    	ans.first=(ans.first&l1[x])|(~ans.first&l0[x]);
    	ans.second=(ans.second&l1[x])|(~ans.second&l0[x]);
    	return ;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)query1(x<<1,l,mid,ql,qr);
        if(qr>mid)query1(x<<1|1,mid+1,r,ql,qr);
    }
    
    void query2(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
    	ans.first=(ans.first&r1[x])|(~ans.first&r0[x]);
    	ans.second=(ans.second&r1[x])|(~ans.second&r0[x]);
    	return ;
        }
        int mid=(l+r)>>1;
        if(qr>mid)query2(x<<1|1,mid+1,r,ql,qr);
        if(ql<=mid)query2(x<<1,l,mid,ql,qr);
    }
    
    int son[MAXN],num[MAXN],dep[MAXN],fa[MAXN];
    void dfs1(int x,int pre,int deep){
        fa[x]=pre;num[x]=1;dep[x]=deep+1;
        link(x)if(j->t!=pre){
    	dfs1(j->t,x,deep+1);
    	num[x]+=num[j->t];
    	if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
        }
    }
    
    void dfs2(int x,int td){
        tp[x]=td;p[x]=++cnt;fp[p[x]]=x;
        if(son[x]!=-1)dfs2(son[x],td);
        link(x)if(j->t!=son[x]&&j->t!=fa[x])dfs2(j->t,j->t);
    }
    
    pii st[MAXN];int tot;
    
    void solve(int u,int v,ll z){
        int uu=tp[u];int vv=tp[v];
        ans.first=0;ans.second=base;
        tot=0;
        while(uu!=vv){
    	if(dep[uu]>dep[vv])query2(1,1,n,p[uu],p[u]),u=fa[uu],uu=tp[u];
    	else st[++tot]=mp(p[vv],p[v]),v=fa[vv],vv=tp[v];
        }
        if(dep[u]>dep[v])query2(1,1,n,p[v],p[u]);
        else query1(1,1,n,p[u],p[v]);
        dec(i,tot,1)query1(1,1,n,st[i].first,st[i].second);
        ll ans1=0;ll maxx=0;
        for(int i=k-1;i>=0;i--){
    	int t1=((ans.first>>i)&1);
    	int t2=((ans.second>>i)&1);
    	if(t1&&t2)maxx+=(1ll<<i);
    	else if(t1&&!t2)maxx+=(1ll<<i);
    	else if(!t1&&t2){
    	    if(ans1+(1ll<<i)<=z)ans1+=(1ll<<i),maxx+=(1ll<<i);
    	}
        }
        printf("%llu
    ",maxx);
    }
    
    
    int main(){
        n=read();m=read();k=read();
        for(int i=0;i<k;i++)base|=(1ULL<<i);
        inc(i,1,n)son[i]=-1;
        inc(i,1,n)opt[i]=read(),a[i]=read();
        int u,v;
        inc(i,2,n)u=read(),v=read(),add(u,v),add(v,u);
        dfs1(1,0,0);dfs2(1,1);built(1,1,n);
        int x,y,op;ll z;
        while(m--){
    	op=read();x=read();y=read();z=read();
    	if(op==1)solve(x,y,z);
    	else opt[x]=y,a[x]=z,update(1,1,n,p[x]);
        }
        return 0;
    }
    

      

    4811: [Ynoi2017]由乃的OJ

    Time Limit: 6 Sec  Memory Limit: 256 MB
    Submit: 740  Solved: 271
    [Submit][Status][Discuss]

    Description

    由乃正在做她的OJ。现在她在处理OJ上的用户排名问题。OJ上注册了n个用户,编号为1~",一开始他们按照编号
    排名。由乃会按照心情对这些用户做以下四种操作,修改用户的排名和编号:然而由乃心情非常不好,因为Deus天
    天问她题。。。因为Deus天天问由乃OI题,所以由乃去学习了一下OI,由于由乃智商挺高,所以OI学的特别熟练她
    在RBOI2016中以第一名的成绩进入省队,参加了NOI2016获得了金牌保送
    Deus:这个题怎么做呀?
    yuno:这个不是NOI2014的水题吗。。。
    Deus:那如果出到树上,多组链询问,带修改呢?
    yuno:诶。。。???
    Deus:这题叫做睡觉困难综合征哟~
    虽然由乃OI很好,但是她基本上不会DS,线段树都只会口胡,比如她NOI2016的分数就是100+100+100+0+100+100。
    。。NOIP2017的分数是100+0+100+100+0+100所以她还是只能找你帮她做了。。。
    给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示。
    每次询问包含三个数x,y,z,初始选定一个数v。然后v依次经过从x到y的所有节点,每经过一个点i,v就变成v opti
     xi,所以他想问你,最后到y时,希望得到的值尽可能大,求最大值?给定的初始值v必须是在[0,z]之间。每次修
    改包含三个数x,y,z,意思是把x点的操作修改为y,数值改为z

    Input

    第一行三个数n,m,k。k的意义是每个点上的数,以及询问中的数值z都 <2^k。之后n行
    每行两个数x,y表示该点的位运算编号以及数值
    之后n - 1行,每行两个数x,y表示x和y之间有边相连
    之后m行,每行四个数,Q,x,y,z表示这次操作为Q(1位询问,2为修改),x,y,z意义如题所述
    0 <= n , m <= 100000 , k <= 64

    Output

    对于每个操作1,输出到最后可以造成的最大刺激度v

    Sample Input

    5 5 3
    1 7
    2 6
    3 7
    3 6
    3 1
    1 2
    2 3
    3 4
    1 5
    1 1 4 7
    1 1 3 5
    2 1 1 3
    2 3 3 3
    1 1 3 2

    Sample Output

    7
    1
    5

    HINT

     

    Source

  • 相关阅读:
    江西财经大学第一届程序设计竞赛 I 题 小P和小Q
    江西财经大学第一届程序设计竞赛 H题- 小P的数学问题
    C# 窗体
    数据库操作(对战游戏)
    数据库操作 (数据操作类)
    练习
    泛型集合
    数据库操作 (防注入攻击)
    数据库操作(增删改)
    DO.NET操作数据库
  • 原文地址:https://www.cnblogs.com/wang9897/p/10363462.html
Copyright © 2020-2023  润新知