zoukankan      html  css  js  c++  java
  • NOIP模拟赛17

    5分。。。。

    T1 LOJ 计算几何瞎暴力

    维护以下操作:

    1、序列末尾加一个数

    2、序列全体从小到大排序

    3、查询区间和

    4、序列全体异或一个数k

    序列全体异或一个数,很明显是trie树

    那么序列全体从大到小排序就是把一个个数插入trie树的过程

    那么就需要一个数组,存储还没有插入trie树的数

    全体异或:

    这里需要两个标记:

    xortag表示当前序列是异或了什么,

    trie树里1个tag 表示trie树是在异或了tag之后有序

    为什么需要标记?

    假设当前是二进制第i位,如果i&标记的第i位为真,那么查询的时候1相当于0,0相当于1

    为什么要两个标记?

    因为有可能对全体执行异或操作,这样原来有序的trie树直接异或就无序了。

    所以tag用来表示trie树在当前tag下是有序的序列

    查询子树和时,用xortag

    在判断向左还是向右走时,要用trie树里的tag

    因为trie树里的顺序不变

    有了标记,查询区间和时,需要维护的就是二进制的每一位1的出现次数

    如果&标记的第i为为真,就用0的个数

    否则用1的个数

    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    #define N 200001
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    int xortag,bit[31];
    struct TRIE
    {
        int len,tag,root;
        int ch[N*31][2],sum[N*31][31],siz[N*31];
        TRIE()
        {
            len=0;
            tag=0;
            root=0;
        }
        void insert(int x)
        {
            int rt=root,id;
            for(int i=29;i>=0;--i)
            {
                id=(x&bit[i])>0;
                if(!ch[rt][id]) ch[rt][id]=++len;
                rt=ch[rt][id];
                siz[rt]++;
                for(int j=0;j<30;++j) 
                    if(x&bit[j]) sum[rt][j]++;
            }
        }
        LL getsum(int x)
        {
            LL ans=0;
            for(int i=0;i<30;++i)
                if(xortag&bit[i]) ans+=1ll*(siz[x]-sum[x][i])*bit[i];
                else ans+=1ll*sum[x][i]*bit[i];
            return ans;
        }
        LL query(int x)
        {
            if(!x) return 0;
            int rt=root,l,r;
            LL ans=0;
            for(int i=29;i>=0;--i)
            {
                l=0,r=1;
                if(tag&bit[i]) swap(l,r);
                if(x<=siz[ch[rt][l]]) rt=ch[rt][l];
                else
                {
                    ans+=getsum(ch[rt][l]);
                    x-=siz[ch[rt][l]];
                    rt=ch[rt][r];
                }
            }
            ans+=getsum(rt)/siz[rt]*x;
            return ans;
        }
        int getsiz()
        {
            return siz[ch[root][0]]+siz[ch[root][1]];
        }
    }Trie;
    struct ARRAY
    {
        int len;
        ARRAY()
        {
            len=0;
        }
        int sum[N][31],a[N];
        void insert(int x)
        {
            x^=xortag;
            a[++len]=x;
            for(int i=29;i>=0;i--)
                if(x&bit[i]) sum[len][i]=sum[len-1][i]+1;
                else sum[len][i]=sum[len-1][i];
        }
        void transfer()
        {
            Trie.tag=xortag; 
            for(int i=1;i<=len;i++) Trie.insert(a[i]); 
            len=0;
         }
         LL query(int x)
         {
             LL ans=0;
            for(int i=0;i<30;++i)
                 if(xortag&bit[i]) ans+=1ll*(x-sum[x][i])*bit[i];
                 else ans+=1ll*sum[x][i]*bit[i];
             return ans;
        }
    }Array;
    LL query(int x)
    {
        int siz=Trie.getsiz();
        if(x<=siz) return Trie.query(x);
        else return Trie.query(siz)+Array.query(x-siz);
    }
    int main()
    {
        freopen("seko.in","r",stdin);
        freopen("seko.out","w",stdout);
        bit[0]=1;
        for(int i=1;i<=30;i++) bit[i]=bit[i-1]<<1;
        int n,m,x;
        read(n);
        for(int i=1;i<=n;++i) read(x),Array.insert(x);
        read(m);
        int ty,u,v;
        while(m--)
        {
            read(ty);
            if(ty==1)
            {
                read(v);
                Array.insert(v);
            }
            else if(ty==2) Array.transfer();
            else if(ty==3)
            {
                read(u);read(v);
                printf("%I64d
    ",query(v)-query(u-1));
            }
            else 
            {
                read(v);
                xortag^=v;
            }
        }
        return 0;
    }
    View Code

    T2  [ZJOI2008]骑士

    基环树DP,断环为链合并

    为什么做最大点权独立集不对?

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 1000001
    using namespace std;
    typedef long long LL;
    int n,num;
    int to[N<<1],nxt[N<<1],front[N],val[N];
    int dfn[N],low[N],st[N],top,tot=1,ai[N];
    bool cir[N],vis[N];
    LL dp[N][2],bi[N][2],ans2,ans;
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    void init()
    {
        read(n);
        int y;
        for(int i=1;i<=n;i++) 
        {
            read(val[i]),read(y);
            add(i,y);
        }
    }
    void tarjan(int u,int pre)
    {
        low[u]=dfn[u]=++tot;
        st[++top]=u;
        vis[u]=true;
        for(int i=front[u];i;i=nxt[i])
        {
            if(i==(pre^1)) continue;
            
                if(!dfn[to[i]]) { tarjan(to[i],i); low[u]=min(low[u],low[to[i]]); }
                else low[u]=min(low[u],dfn[to[i]]),vis[to[i]]=true;
        }
        if(low[u]==dfn[u])
        {
            if(st[top]==u) top--;
            else
            {    
                while(st[top]!=u) 
                {
                    cir[st[top]]=true;
                    ai[++num]=st[top--];
                }
                top--,ai[++num]=u;
                cir[u]=true;
            }
        }
    }
    void dfs(int x,int fa)
    {
        dp[x][1]=val[x];
        int t;
        for(int i=front[x];i;i=nxt[i])
        {
            t=to[i];
            if(cir[t] || t==fa) continue;
            dfs(t,x);
            dp[x][0]+=max(dp[t][0],dp[t][1]);
            dp[x][1]+=dp[t][0];
        }
    }
    void unionn()
    {
        int tot,t; LL tmp; 
        for(int i=1;i<=n;i++)
        {
            if(vis[i]) continue;
            ans=0;num=0;top=0;
            tarjan(i,0);
            for(int i=1;i<=num;i++) dfs(ai[i],0);
            bi[1][0]=dp[ai[1]][0],bi[1][1]=0;
            for(int i=2;i<=num;i++)
            {
                bi[i][0]=dp[ai[i]][0];
                bi[i][1]=dp[ai[i]][1];
                bi[i][0]+=max(bi[i-1][0],bi[i-1][1]);
                bi[i][1]+=bi[i-1][0];
            }
            ans=max(bi[num][1],bi[num][0]);
            bi[1][0]=0,bi[1][1]=dp[ai[1]][1];
            for(int i=2;i<=num;i++)
            {
                bi[i][0]=dp[ai[i]][0];
                bi[i][1]=dp[ai[i]][1];
                bi[i][0]+=max(bi[i-1][0],bi[i-1][1]);
                bi[i][1]+=bi[i-1][0];
            }
            ans=max(ans,bi[num][0]);
            ans2+=ans;
        }
        printf("%lld",ans2);
    }
    int main()
    {
        //freopen("hoyin.in","r",stdin);
    //    freopen("hoyin.out","w",stdout);
        init();
        unionn();
    }
    View Code

    T3 [Ynoi2017]由乃的玉米田

    http://www.lydsy.com/JudgeOnline/problem.php?id=4810

    莫队+bitset

    维护两个bitset

    第i位表示是否存在值为i的数

    一个正着的A,一个反着的B

    1、xi-xj=d  ==> xi=d+xj,所以如果 A&A(<<d)有一位为真,就存在 (右移也行)

    2、xi+xj=d ==> xi=-xj+d,有负数不好处理,所以 ==> xi=N-xj+d-N=(N-xj)-(N-d) 

         所以若A&(B>>(N-d))有一位为真,就存在

    3、xi*xj=d,根号d枚举d的约数,判断是否存在

    #include<cstdio>
    #include<bitset>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define N 100001
    using namespace std;
    bitset <N> A,B;
    int n,m,siz;
    int a[N],bl[N];
    int sum[N];
    bool ans[N];
    struct node
    {
        int ty,l,r,d;
        int id;
    }e[N];
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    bool cmp(node p,node q)
    {
        if(bl[p.l]!=bl[q.l]) return bl[p.l]<bl[q.l];
        return p.r<q.r;
    }
    void update(int pos,bool w)
    {
        if(w)
        {
            A[a[pos]]=1;
            B[N-a[pos]]=1;
            sum[a[pos]]++;
        }
        else
        {
            sum[a[pos]]--;
            if(!sum[a[pos]]) A[a[pos]]=0,B[N-a[pos]]=0;
        }
    }
    bool solve(int i)
    {
        if(e[i].ty==1) return (A&(A<<e[i].d)).any();
        if(e[i].ty==2) return (A&(B>>(N-e[i].d))).any();
        int d=e[i].d;
        if(!d) return sum[0];
        for(int j=1;j*j<=d;j++) 
            if(!(d%j) && sum[j] && sum[d/j]) return true;
        return false;
    }
    int main()
    {
        freopen("baka.in","r",stdin);
        freopen("baka.out","w",stdout);
        read(n); read(m);
        siz=sqrt(n);
        for(int i=1;i<=n;i++) bl[i]=(i-1)/siz+1;
        for(int i=1;i<=n;i++) read(a[i]);
        for(int i=1;i<=m;i++)
        {
            read(e[i].ty);read(e[i].l);read(e[i].r);read(e[i].d);
            e[i].id=i;
        }
        sort(e+1,e+m+1,cmp);
        int L=1,R=0,l,r;
        for(int i=1;i<=m;i++)
        {
            l=e[i].l; r=e[i].r;
            while(R<r) update(++R,1);
            while(R>r) update(R--,0);
            while(L<l) update(L++,0);
            while(L>l) update(--L,1);
            ans[e[i].id]=solve(i);
        }
        for(int i=1;i<=m;i++) puts(ans[i] ? "seko" : "baka");
    }
    View Code
  • 相关阅读:
    [uiautomator篇] UiWatcher的使用
    [android开发篇]安装android sdk的时候请注意
    Oracle to_char格式化函数
    SharePoint2010主题和样式揭秘
    场解决方案添加webpart(Create Webpart to page using code)
    SharePoint Site Pages & Application Pages
    Sharepoint的网页(Page),网页解析(Parsing)与解析安全处理(Security)
    用PowerShell批量部署wsp包
    用PowerShell批量收回wsp包
    SharePoint 2010 PowerShell 系列 之 备份、还原、部署 .WSP
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7607514.html
Copyright © 2011-2022 走看看