• 2019.3.5考试


    题目见LOJ

    T1 决斗

    40pts直接贪心

    考虑我们主要的问题是多人经过一个点,我们找出没有人继续向前走的那个点(容易想到至少存在一个这样的点),然后从那个点下一个点开始贪心就行了

    具体怎么找?对每个点的人数(减一)做前缀和,前缀和最小的地方就是那个点、

    (因打字带空格,printf("%d",ans);变成printf("%d ",ans);,导致不忽略行末空格的情况下成功gg

     1 #include<set>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define sint set<int>
     7 #define sit set<int>::iterator
     8 #define vint vector<int>
     9 #define vit vector<int>::iterator
    10 using namespace std;
    11 const int N=500005;
    12 int n,sum,ans,minn,noww;
    13 int a[N],dwf[N],elf[N];
    14 vint ve[N]; sint st;
    15 int main()
    16 {
    17     scanf("%d",&n),noww=1,minn=n+1;
    18     for(int i=1;i<=n;i++)
    19     {
    20         scanf("%d",&a[i]);
    21         ve[a[i]].push_back(i);
    22     }
    23     for(int i=1;i<=n;i++) scanf("%d",&dwf[i]);
    24     for(int i=1;i<=n;i++) scanf("%d",&elf[i]);
    25     for(int i=1;i<=n;i++)
    26     {
    27         sum+=ve[i].size()-1;
    28         if(sum<minn) minn=sum,noww=i;
    29     }
    30     if(++noww>n) noww=1;
    31     for(int i=1;i<=n;i++)
    32     {
    33         vint v=ve[noww];
    34         for(vit it=v.begin();it!=v.end();it++)
    35             st.insert(elf[*it]);
    36         sit ir=st.lower_bound(dwf[noww]);
    37         if(ir==st.end()) st.erase(st.begin());
    38         else ans++,st.erase(ir); 
    39         if(++noww>n) noww=1;
    40     }
    41     printf("%d",ans);
    42     return 0;
    43 }
    View Code

    T2 数列

    把序列反过来接在前面,这样在左边写数相当于在前半部分选,再右边写数相当于在后半部分选

    (然后考试的时候就在第二问上墨迹了半天

    维护一个权值树状数组,记录以每个数结尾的长度和出现在不同写法序列中的总方案,然后长度相同时合并答案。最终答案即 方案数* 2^(总长度-LIS长度-1)(除了LIS以外的都可以在两边随便填,还要刨掉第一个填上去的)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=400005,mod=1e9+7;
     6 struct a{int len,cnt;}bit[N];
     7 void Add(int &x,int y)
     8 {
     9     x+=y;
    10     if(x>=mod) x-=mod;
    11 }
    12 a operator + (a x,a y)
    13 {
    14     int l1=x.len,l2=y.len;
    15     if(l1^l2) return l1>l2?x:y;
    16     else return (a){l1,(x.cnt+y.cnt)%mod};
    17 }
    18 int uni[N],b[N],n,rd,lth;
    19 a Query(int pos)
    20 {
    21     a ret=(a){0,0};
    22     while(pos)
    23     {
    24         ret=ret+bit[pos];
    25         pos-=pos&-pos;
    26     }
    27     return ret;
    28 }
    29 void Change(int pos,a tsk)
    30 {
    31     while(pos<=lth)
    32     {
    33         bit[pos]=bit[pos]+tsk;
    34         pos+=pos&-pos;
    35     }
    36 }
    37 int Qpow(int x,int k)
    38 {
    39     if(k==1) return x;
    40     int tmp=Qpow(x,k/2);
    41     return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
    42 }
    43 int main()
    44 {
    45     scanf("%d",&n);
    46     for(int i=1;i<=n;i++)
    47     {
    48         scanf("%d",&rd);
    49         uni[i]=b[i+n]=b[n-i+1]=rd;
    50     }
    51     sort(uni+1,uni+1+n);
    52     lth=unique(uni+1,uni+1+n)-1-uni,n*=2;
    53     for(int i=1;i<=n;i++)
    54         b[i]=lower_bound(uni+1,uni+1+lth,b[i])-uni;
    55     for(int i=1;i<=n;i++)
    56     {
    57         a qry=Query(b[i]-1);
    58         if(++qry.len==1) qry.cnt=1;
    59         Change(b[i],qry);
    60     }
    61     a ans=Query(lth); n>>=1;
    62     if(ans.len==n) printf("%d 1",n);
    63     else printf("%d %lld",ans.len,1ll*ans.cnt*Qpow(2,n-ans.len-1)%mod);
    64     return 0;
    65 }
    View Code

    T3 打苍蝇

    判断点是否在多边形内->THUPC2018 赛艇,告辞

  • 相关阅读:
    SharePoint Development
    win32- copyfile的使用
    SetWindowHookEx的复习
    C++ vector的使用
    关于char * 和 char [] 的一点理解
    CreateThread
    C++字符串大写字母转小写字母
    字符串逆序
    使用RegSetValueEx创建键值
    EnumColorProfiles WcsGetDefaultColorProfile WcsSetDefaultColorProfile的使用
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10476899.html
Copyright © 2020-2023  润新知