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 赛艇,告辞

posted @ 2019-03-05 15:05  Speranza_Leaf  阅读(147)  评论(0)    收藏  举报