zoukankan      html  css  js  c++  java
  • 19CSP-S十一高端峰会—青岛站 题解

     T1

    写一下考场上的思路8 反正看到 我第一眼觉得是个解析几何 后来我竟然有个鬼畜的想法 我竟然想求出所有直线焦点的坐标

    后来 我发现 这个做法非常的不科学 甚至就达到了n^2 的复杂度 但是 求出来坐标也没什么用 很自闭

    后来我yy了几个很大的图 然后 模拟了一遍题目 发现画了很多很多的点的图 发现答案都是3 当时 我就思考 会不会没有4的情况

    然后 大胆 猜结论 不存在4的情况 所以 我们 简单证明一下这个结论 没有4个点的完全图

    其实有一种比较严谨的证明方法 :

    考虑构造 每个点p 只会被两条直线 所以不会有4个点是相邻的 所以考虑 将x y排序 考虑到p时 使用相邻没使用过的颜色即可 

    所以 存在3种颜色的时候 存在三个不同的 斜率即可 2种颜色的时候 大于2条直线并且 只存在2个斜率 1个 和 0个 应该不用说吧

    #include<bits/stdc++.h>
    #define eps 1e-10
    #define INF 2000000010
    #define inf 2000000100
    using namespace std;
    const int N=1000010;
    int n,flag,mark,res1,T;
    long double s1,s2;
    char buf[1<<15],*fs,*ft;
    inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    inline int read() {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    struct gg {
        long double s;
    }t[N];
    typedef long double ld;
    inline bool check(long double a,long double b) {
        if(fabs(a-b)<=eps) return 1;
        return 0;
    }
    //可以证明的是 不存在 >4 的情况 因为不存在 4个点的 完全图
    //3的情况 是 存在三角形  
    //2的情况 类似 网格图 
    int main() {
        //freopen("1.in.cpp","r",stdin);
        T=read();
        while(T--) {
            n=read();
            flag=res1=mark=0;s1=inf;s2=inf;
            for(int i=1;i<=n;++i) {
                long double x,y,xx,yy;
                x=read(); y=read();
                xx=read(); yy=read();
                if(y<yy) {
                    swap(x,xx);
                    swap(y,yy);
                }
                if(x==xx) {
                    t[i].s=INF;
                    continue;
                }
                t[i].s=(y-yy)/(x-xx);
            }
            for(int i=1;i<=n;++i) {
                if(check(s1,inf)) {
                    s1=t[i].s;
                    continue;
                }
                if(check(s1,t[i].s)) { 
                    mark=1;
                    continue;
                }
                if(check(s2,inf)) {
                    s2=t[i].s;
                    res1=1;
                    continue;
                }
                if(check(s2,t[i].s)) {
                    mark=1;
                    continue;
                }
                flag=1;
            }
            if(flag) {
                puts("3");
                continue;
            }
            if(res1&&mark) {
                 puts("2");
                continue;
            }
            if(res1) {
                puts("1");
                continue;
            }
            puts("0");
            continue;
        }
        return 0;
    }

     T2 

    反正是个贪心吧 反正考场上只会写贪心 假设i在j之前的贡献 和j在i之前的贡献 分别写出来 然后 考虑 什么情况下

    i在j之前贡献较大的前提下就是 ti*pj<pi*tj 然后排序 写了个nmlogn的复杂度 水了70 

    但是 考虑怎么优化 有个比较巧妙的思路

    考虑将m离线 那么就是每次在元素中 插入一个位置 然后删除原来的位置 然后考虑这个时候 对答案带来的贡献

    首先对于他自己位置的贡献 只和它前面位置T之和有关 然后对后面的贡献 只和后面的P之和有关

    然后考虑一种数据结构 支持查询 区间和就行了

    然后考虑将所有n+m中都排序 这个时候就空出来了n+m个位置 然后将前n个插进去 然后考虑 这m个 每次更改删除 插入即可

    因为此时有空位置 所以不用 考虑整个序列的移动了 思想很巧妙

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &x) {
        x=0;T f=1,ch=getchar();
        while(!isdigit(ch))     {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x*=f;
    } 
    const int N=200010;
    const int M=100010; 
    ll n,m,T,x,pi,ti;
    struct gg {
        ll p,t,id;
    }a[M],t[M],s[N]; 
    int c[N],q[N];//两个BIT c:t q:p 
    int pos[N];
    inline ll lowbit(ll x) {return x&(-x);}
    inline void add(ll x,ll d) {
        for(;x<=n+m;x+=lowbit(x)) {
            c[x]+=d;
        }
    }
    inline void add1(ll x,ll d) {
        for(;x<=n+m;x+=lowbit(x)) {
            q[x]+=d;
        }
    }
    inline ll query(ll x) {//查询t 
        ll res=0;
        for(;x;x-=lowbit(x)) {
            res+=c[x];     
        } 
        return res;
    } 
    inline ll query1(ll x) {//查询p 
        ll res=0;
        for(;x;x-=lowbit(x)) {
            res+=q[x];
        }
        return res;
    }
    inline bool mycmp(gg x,gg y) {
        return x.t*y.p<y.t*x.p;
    }
    int main() {
        //freopen("1.in.cpp","r,",stdin);
        read(n); read(m); read(T);
        for(int i=1;i<=n;i++) {
            read(a[i].p); read(a[i].t);
            a[i].id=i; s[i]=a[i];
        }
        for(int i=1;i<=m;i++) {
            read(x); read(pi); read(ti);
            gg k=(gg){pi,ti,i+n};
            s[i+n]=k;
            k.id=x;
            t[i]=k;
        }
        sort(s+1,s+n+m+1,mycmp);
        for(int i=1;i<=n+m;i++) pos[s[i].id]=i;//cout<<pos[s[i].id]<<" "<<s[i].id<<endl;
        for(int i=1;i<=n;i++) {
            add(pos[i],a[i].t); add1(pos[i],a[i].p);
        }
        ll ans=0;
        for(int i=1;i<=n;i++) {
            ans+=1ll*a[i].p*(T-query(pos[i]));
        }
        printf("%lld
    ",ans);
        for(int i=1;i<=m;i++) {
            ans-=1ll*a[t[i].id].p*(T-query(pos[t[i].id]));//减去之前的贡献 
            add(pos[t[i].id],-a[t[i].id].t);
            add1(pos[t[i].id],-a[t[i].id].p);
            ans+=1ll*(query1(n+m)-query1(pos[t[i].id]))*a[t[i].id].t;
            ans-=1ll*(query1(n+m)-query1(pos[i+n]))*t[i].t;
            add(pos[i+n],t[i].t);
            add1(pos[i+n],t[i].p);
            ans+=1ll*(T-query(pos[i+n]))*t[i].p;
            a[t[i].id]=t[i];
            printf("%lld
    ",ans);
        }
        return 0;
    } 

     T3

    不会写 数位DP 水了30 咕咕咕了

     

  • 相关阅读:
    Socket
    剑指 Offer 14- I. 剪绳子
    剑指 Offer 29. 顺时针打印矩阵
    判断二分图
    vue生命周期以及常用标签
    滑动窗口
    二叉树
    常用算法
    动态规划
    蓄水池抽样
  • 原文地址:https://www.cnblogs.com/Tyouchie/p/11625671.html
Copyright © 2011-2022 走看看