20191006

Posted blogofchc1234567890

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20191006相关的知识,希望对你有一定的参考价值。

A.

二分图+乱搞的做法被叉掉了。
先求出最多能赢多少次,然后枚举 (a_i) ,二分答案能与之匹配的 (b_j) ,check函数判断 (a_i)(b_j) 匹配时答案是否会变小。二分完之后把对应的 (b_j) 删掉。

Code

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int maxn=1003;
int n,tot,p[maxn],ANS[maxn];
bool del[maxn];
vector<P> a;
vector<int> b;
bool check(int res,int x){
    int tmp=b[x];
    b.erase(b.begin()+x);
    for(int i=-1,j=-1;;){
        for(i++;i<int(a.size())&&del[i];i++);
        if(i==int(a.size()))break;
        for(j++;j<int(b.size())&&b[j]<=a[i].first;j++);
        if(j==int(b.size()))break;
        res++;
    }
    b.insert(b.begin()+x,tmp);
    return res==tot;
}
int main(){
    scanf("%d",&n);
    a.resize(n),b.resize(n);
    for(int i=0;i<n;i++)scanf("%d",&a[i].first),a[i].second=i;
    for(int i=0;i<n;i++)scanf("%d",&b[i]);
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    for(int i=0;i<n;i++)p[a[i].second]=i;
    for(int i=0,j=-1;i<n;i++){
        for(j++;j<n&&b[j]<=a[i].first;j++);
        if(j==n)break;
        tot++;
    }
    for(int i=0;i<n;i++){
        int x=a[p[i]].first,q=upper_bound(b.begin(),b.end(),x)-b.begin();
        del[p[i]]=1;
        int l=0,r=q-1,mid,ans1=-1,ans2=-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(0,mid))ans1=mid,l=mid+1;
            else r=mid-1;
        }
        l=q,r=int(b.size())-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(1,mid))ans2=mid,l=mid+1;
            else r=mid-1;
        }
        if(ans2==-1)ans2=ans1;
        else tot--;
        ANS[i]=b[ans2];
        b.erase(b.begin()+ans2);
    }
    for(int i=0;i<n;i++)printf("%d ",ANS[i]);
    return 0;
}

B.

考虑二分答案(角度)。

解 1

对于一个角度 ( heta) ,画一条与x轴夹角为 ( heta) 的直线,保证其在所有点的下方,然后将所有点按到该直线的距离从小到大排序,距离相同的按y坐标从大到小排序。然后把y坐标离散,用树状数组计算每个点的贡献。如果贡献之和 (geq) 中位数,左移右端点。
卡精度。

解 2

考虑
(frac{y_j-y_i}{x_j-x_i}>k(x_i<x_j))
(y_j-y_i>kx_j-kx_i)
(y_j-kx_j>y_i-kx_i)

对于每个点 ((x_i,y_i)) 算出 (y_i-kx_i) 然后二维数点。

Code 1

#include<bits/stdc++.h>
using namespace std;
typedef long long D;
const int maxn=50003;
const double pi=acos(-1),eps=1e-12;
int sgn(double x){return x<-eps?-1:x>eps;}
struct point{
    D x,y;
    point(){}
    point(D _x,D _y):x(_x),y(_y){}
}a[maxn];
int n,cntmp,t[maxn];
D mp[maxn];
double cot_mid;
void add(int pos,int k){while(pos)t[pos]+=k,pos-=pos&-pos;}
int query(int pos){int ret=0;while(pos<=cntmp)ret+=t[pos],pos+=pos&-pos;return ret;}
bool cmp(const point &p,const point &q){
    int tmp=sgn(p.x-mp[p.y]*cot_mid-(q.x-mp[q.y]*cot_mid));
    return tmp?tmp>0:q.y>p.y;
}
D f(double x){
    cot_mid=cos(x)/sin(x);
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=cntmp;i++)t[i]=0;
    D ret=0;
    for(int i=1;i<=n;i++){
        int tmp=query(a[i].y);
        ret+=tmp;
        add(a[i].y,1);
    }
    return ret;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y),mp[++cntmp]=a[i].y;
    sort(mp+1,mp+cntmp+1);
    cntmp=unique(mp+1,mp+cntmp+1)-mp-1;
    for(int i=1;i<=n;i++)a[i].y=lower_bound(mp+1,mp+cntmp+1,a[i].y)-mp;
    D N=1ll*n*(n-1)/2,rnk1=(N+1)/2,rnk2=N/2+1;
    double l=0,r=pi,mid,ans1=-1,ans2=-1;
    while(sgn(r-l)>0){
        mid=(l+r)/2;
        if(f(mid)>=rnk1)ans1=mid,r=mid-eps;
        else l=mid+eps;
    }
    l=0,r=pi;
    while(sgn(r-l)>0){
        mid=(l+r)/2;
        if(f(mid)>=rnk2)ans2=mid,r=mid-eps;
        else l=mid+eps;
    }
    printf("%.10lf
",N&1?ans1:(ans1+ans2)/2);
    return 0;
}

C.

考虑对于一个点 (u) ,在完整图中所有与 (u) 相邻的、编号比 (u) 大的节点的颜色都不能相同,因为都有边。所以 (u)(n-( ext{所有与}u ext{相邻的、编号比}u ext{大的节点个数})) 种取值。
如何维护完整图中所有与 (u) 相邻的、编号比 (u) 大的节点?线段树合并或set启发式合并。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=100003,mod=998244353;
int mul(long long x,int y){return x*y%mod;}
vector<int> g[maxn];
int n,m,f[maxn];
set<int> st[maxn];
int find(int x){return x!=f[x]?f[x]=find(f[x]):f[x];}
void merge(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx!=fy){
        if(st[fx].size()<st[fy].size())swap(fx,fy);
        while(!st[fy].empty())st[fx].insert(*st[fy].begin()),st[fy].erase(st[fy].begin());
        f[fy]=fx;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        if(u>v)swap(u,v);
        g[u].push_back(v),g[v].push_back(u);
        st[u].insert(v);
    }
    int ans=1;
    for(int u=1;u<=n;u++){
        for(int v:g[u])if(v<u)merge(u,v);
        int fu=find(u);
        if(st[fu].count(u))st[fu].erase(u);
        ans=mul(ans,n-st[fu].size());
    }
    printf("%d
",ans);
    return 0;
}

以上是关于20191006的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器