zoukankan      html  css  js  c++  java
  • UOJ Test Round 3

    A.几何冲刺

    感觉自己的智商爆炸。

    显然是按照极角序排列之后依次加点,判断是否有点。

    保证一个点在两个角的范围内就OK了啊,想了半天叉积。。。

    #include "triangles.h"
    #include <bits/stdc++.h>
    #define for1(a,b,i) for(int i=a,end_=b;i<=end_;++i)
    #define FOR2(a,b,i) for(int i=a,end_=b;i>=end_;--i)
    using namespace std;
    typedef long long ll;
    #define M 20005
    
    
    struct node {
        int id,x,y;
        double c;
        
        
        inline bool operator <(const node &a) const {
            return c<a.c;
        }
    }a[M];
    
    const double pi=acos(-1);
    
    void check_triangles(int n,int m,int *ax,int *ay,int *bx,int *by,int **f) {
        for1(1,n,i) a[i]=(node){i,ax[i-1],ay[i-1]};
        for1(1,m,i) a[i+n]=(node){i+n,bx[i-1],by[i-1]};
        for1(1,n+m,i) a[i].c=atan2(a[i].y,a[i].x);
        sort(a+1,a+n+m+1);
        
        for1(1,n+m,i) a[n+m+i]=a[i],a[n+m+i].c+=2*pi;
        int tot=2*(n+m);
        for1(1,n,i) for1(i+1,n,j) f[i-1][j-1]=-1;
        for(int l=1;l<=n+m;++l) {
            while (l<=n+m&&a[l].id>n) ++l;
            if(l>n+m) break;
            bool t=a[l].c<0;
            int pos=l,Max_pos=-1;
            double num=a[l].c+pi,Max=-1e18;
            while (pos<tot&&a[pos+1].c<num) {
                ++pos;
                //这里可以改成向量会快很多
                double x=atan2(a[pos].y-a[l].y,a[pos].x-a[l].x);
                if(!t&&x<0) x+=2*pi;
                
                if(a[pos].id>n) {
                    if(x>Max) {
                        Max=x;
                        Max_pos=a[pos].id-n-1;
                    }
                }
                else {
                    if(x<Max) {
                        int x_[2]={a[l].id,a[pos].id};
                        if(x_[0]>x_[1]) swap(x_[0],x_[1]);
                        f[x_[0]-1][x_[1]-1]=Max_pos;
                    }
                }
            }
        }
    }
    View Code

    B.去月球

    感觉我写的hash+线段树做法挺显然的吧,$O(m*log^2n)$。

    然后优化就可以用后缀自动机搞个$O(1)$lca就OK了,但是太码农了,没写。

    myy的思路非常6。

    考虑建出一个trie树,表示$[1,i]$的消除完之后的序列。

    然后$dis(pos[l-1],pos[r])$就是不能得到的点的个数。

    证明的话就是我们考虑在$pos[l-1]$后加上$[l,r]$消除完的区间。

    和$[1,l-1]$内配对的点是一个前缀,对应了走到lca,之后对应了走到pos[r]。

    很巧妙了,$O(n*logn+m*logn)$。

    #include <bits/stdc++.h>
    #include "mythological.h"
    #define for1(a,b,i) for(int i=a,end_=b;i<=end_;++i)
    #define FOR2(a,b,i) for(int i=a,end_=b;i>=end_;--i)
    using namespace std;
    typedef long long ll;
    
    #define M 200005
    int n;
    int a[M],pos[M];
    int dep[M],fa[M][20];
    map <int,int> cc[M];
    
    inline int Lca(int x,int y) {
        if(dep[x]<dep[y]) swap(x,y);
        FOR2(16,0,i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
        if(x==y) return x;
        FOR2(16,0,i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    
    int query(int l,int r) {
        --l;
        return r-l-dep[pos[l]]-dep[pos[r]]+2*dep[Lca(pos[l],pos[r])];
    }
    
    void init(int n_,int _,int s_[],int t) {
        n=n_;
        for1(1,n,i) a[i]=s_[i];
        
        int cur=0;
        for1(1,n,i) {
            if(a[i]==a[cur]) cur=fa[cur][0];
            else {
                if(cc[cur].count(a[i])) cur=cc[cur][a[i]];
                else cc[cur][a[i]]=i,fa[i][0]=cur,cur=i;
            }
            pos[i]=cur;
        }
        for1(1,n,i) dep[i]=dep[fa[i][0]]+1;
        for1(1,16,i) for1(1,n,j) fa[j][i]=fa[fa[j][i-1]][i-1];
    }
    View Code

     C.量子破碎

    fwt的应用。

    $cnt(x&pos)+cnt(y&pos)=cnt(x&y&pos)$

    fwt之后pos点不为0的条件就是上面的式子为偶数。

    然后直接check解就好了。

    #include <bits/stdc++.h>
    #include "quantumbreak.h"
    #define for1(a,b,i) for(int i=a,end_=b;i<=end_;++i)
    #define FOR2(a,b,i) for(int i=a,end_=b;i>=end_;--i)
    using namespace std;
    typedef long long ll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    const int M=(1<<20)+5;
    int ans[M];
    double a[2][2];
    const double c=1/sqrt(2);
    
    int query_xor(int n,int t) {
        int cnt=(1<<n)-1;
        for1(1,(1<<n)-1,i) ans[i]=i;
        
        for1(0,1,i) for1(0,1,j) a[i][j]=c;
        a[1][1]=-c;
        
        while (cnt>1) {
            FOR2(n,1,i) manipulate(a,i-1);
            int tot=0;
            int pos=query();
            for1(1,cnt,i) if(__builtin_parity(ans[i]&pos)==0) ans[++tot]=ans[i];
            cnt=tot; 
        }
        return ans[1];
    }
    View Code
  • 相关阅读:
    CloudFlare Workers 反代任意网站和挂载单页代码
    排查Linux服务器是否有被入侵方法总结
    修复Windows time时间服务无法自动启动的问题
    如何删除windows服务
    linux之NetHogs与nload流量监控
    常用IPV4 DNS服务器与常用IPV6 DNS服务器
    Win10系统如何删除网络及修改网络名称
    window修改远程桌面RDP方法
    单击鼠标右键菜单显示怎么在左边?
    传统IDC机房部署网站
  • 原文地址:https://www.cnblogs.com/asd123www/p/9904302.html
Copyright © 2011-2022 走看看