高一考试的题解

本学校高一同学又迎来了一次考试。
本蒟蒻身为验题人,自然要写一个题解来帮助大家(骗访问量)啦。

T1:
显然满足条件的数mod m相同,这样我们开m个vector把mod m相同的数放进同一个vector里。能否有解判断size即可。
答案要求字典序最小,我们比较这些vector的第一个元素(最小的),显然它们两两不可能相同,所以判断它们的大小即可比较字典序。
(话说这题后70分数据是我造的,前面30分队长说有两个"No",某人排序反了只有20,说明我还把他WA了,嗯,没出锅)
代码:

 1 #include<bits/stdc++.h>
 2 const int maxe=1e6+1e2;
 3 
 4 std::vector<int> v[maxe];
 5 
 6 int main() {
 7     static int n,m,k,t,sel=-1;
 8     scanf("%d%d%d",&n,&k,&m) , assert(m&&m<=1e6);
 9     while(n--) scanf("%d",&t) , v[t%m].push_back(t);
10     for(int i=0;i<m;i++) {
11         if( v[i].size() ) std::sort(v[i].begin(),v[i].end() );
12         if( (signed) v[i].size() >= k && ( !~sel || *v[sel].begin() > *v[i].begin() ) ) sel = i;
13     }
14     if( !~sel ) return puts("No"),0;
15     puts("Yes");
16     for(int i=0;i<k;i++) printf("%d%c",v[sel][i],i!=k-1?' ':'\n');
17     return 0;
18 }
View Code


T2:
这不是裸的三维偏序吗?
一开始队长说256mb内存于是我花了10分钟写了一发树套树。
然后队长说32mb内存于是我又花了10分钟写了一发cdq。
然后队长说数据范围卡cdq,我......
这个三维偏序很特殊,全都是一个排列,我们考虑能否找到什么特殊性质。
一个二元组在三个排列中出现,要么三个顺序,要么有且只有一个顺序(你说两个顺序?我们把这两个元素交换一下就成一个顺序了)。于是我们考虑补集转化,求出非顺序的对数,用C(n,2)去减就是答案。
怎么计算?我们把排列转置一下(a[in[i]]=i),然后两两一组求逆序对。显然一对非顺序的(i,j)会被算且仅算两遍。然后就能得出答案了。
(队长朝我要正好卡掉cdq的数据范围,我说开O2跑1s正解可过1e6,然后他把数据范围设置为2e6开了2s,于是我过了标程TLE了......)
实际上这题复杂度全在IO,于是fread快读大法好。
树套树代码:

 1 #include<bits/stdc++.h>
 2 typedef long long int lli;
 3 const int maxn=1e5+1e2,maxe=1e7+1e2;
 4 
 5 int n;
 6 lli ans;
 7 
 8 struct SegmentTree {
 9     int lson[maxe],rson[maxe],sum[maxe],cnt;
10     inline void insert(int &pos,int l,int r,const int &tar) {
11         if( !pos ) pos = ++cnt;
12         ++sum[pos];
13         if( l == r ) return;
14         const int mid = ( l + r ) >> 1;
15         tar <= mid ? insert(lson[pos],l,mid,tar) : insert(rson[pos],mid+1,r,tar);
16     }
17     inline int query(int pos,int l,int r,const int &ll,const int &rr) {
18         if( !pos || ( ll <= l && r <= rr ) ) return sum[pos];
19         const int mid = ( l + r ) >> 1;
20         if( rr <= mid ) return query(lson[pos],l,mid,ll,rr);
21         else if( ll > mid ) return query(rson[pos],mid+1,r,ll,rr);
22         else return query(lson[pos],l,mid,ll,rr) + query(rson[pos],mid+1,r,ll,rr);
23     }
24 }sgt;
25 
26 struct BinaryIndexTree {
27     int rt[maxn];
28     #define lowbit(x) (x&-x)
29     inline void update(int x,int y) {
30         while( x <= n ) sgt.insert(rt[x],1,n,y) , x += lowbit(x);
31     }
32     inline int query(int x,int y) {
33         int ret = 0; --x , --y;
34         while( x ) ret += sgt.query(rt[x],1,n,1,y) , x -= lowbit(x);
35         return ret;
36     }
37 }bit;
38 
39 struct Point {
40     int z,x,y;
41     friend bool operator < (const Point &a,const Point &b) {
42         return a.z < b.z;
43     }
44 }ps[maxn];
45 
46 int main() {
47     scanf("%d",&n);
48     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].z = i; 
49     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].x = i; 
50     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].y = i; 
51     std::sort(ps+1,ps+1+n);
52     for(int i=1;i<=n;i++) ans += bit.query(ps[i].x,ps[i].y) , bit.update(ps[i].x,ps[i].y);
53     return printf("%lld\n",ans) , 0;
54 }
View Code

CDQ代码:

 1 #include<bits/stdc++.h>
 2 typedef long long int lli;
 3 const int maxn=1e6+1e2,maxe=1e7+1e2;
 4 
 5 int n;
 6 lli ans;
 7 
 8 struct BinaryIndexTree {
 9     int dat[maxn];
10     #define lowbit(x) (x&-x)
11     inline void update(int x,int y) {
12         while( x <= n ) dat[x] += y , x += lowbit(x);
13     }
14     inline int query(int x) {
15         int ret = 0; --x;
16         while(x) ret += dat[x] , x -= lowbit(x);
17         return ret;
18     }
19 }bit;
20 
21 int cmp = 0;
22 struct Point {
23     int z,x,y;
24     friend bool operator < (const Point &a,const Point &b) {
25         return !cmp ? a.z < b.z : ( a.x != b.x ? a.x < b.x : a.y < b.y );
26     }
27 }ps[maxn];
28 
29 inline void solve(int l,int r) {
30     if( l == r ) return;
31     const int mid = ( l + r ) >> 1;
32     solve(l,mid) , solve(mid+1,r);
33     cmp = 1 , std::sort(ps+l,ps+mid+1) , std::sort(ps+mid+1,ps+r+1);
34     int cl = l , cr = mid + 1;
35     while( cl <= mid || cr <= r ) {
36         if( cl > mid ) ans += bit.query(ps[cr++].y);
37         else if( cr > r ) bit.update(ps[cl++].y,1);
38         else if( ps[cl].x <= ps[cr].x ) bit.update(ps[cl++].y,1);
39         else ans += bit.query(ps[cr++].y);
40     }
41     for(int i=l;i<=mid;i++) bit.update(ps[i].y,-1);
42 }
43 
44 int main() {
45     scanf("%d",&n);
46     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].z = i; 
47     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].x = i; 
48     for(int i=1,t;i<=n;i++) scanf("%d",&t) , ps[t].y = i; 
49     cmp = 0 , std::sort(ps+1,ps+1+n) , solve(1,n);
50     return printf("%lld\n",ans) , 0;
51 }
View Code

正解代码:

 1 #pragma GCC optimize(2)
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cctype>
 6 typedef long long int lli;
 7 const int maxn=2e6+1e2;
 8 
 9 int a[maxn],b[maxn],c[maxn],n;
10 lli ans;
11 
12 struct BinaryIndexTree {
13     int dat[maxn];
14     #define lowbit(x) (x&-x)
15     inline void update(int x) {
16         while( x <= n ) ++dat[x] , x += lowbit(x);
17     }
18     inline int query(int x) {
19         int ret = 0;
20         while(x) ret += dat[x] , x -= lowbit(x);
21         return ret;
22     }
23     inline void reset() {
24         memset(dat,0,sizeof(dat));
25     }
26 }bit;
27 
28 struct Point {
29     int x,y;
30     friend bool operator < (const Point &a,const Point &b) {
31         return a.x < b.x;
32     }
33 }ps[maxn];
34 
35 inline lli C(lli n) {
36     return n * ( n - 1 ) / 2;
37 }
38 
39 inline lli calc(int* a,int* b) {
40     lli ret = 0;
41     for(int i=1;i<=n;i++) ps[i] = (Point){a[i],b[i]};
42     bit.reset() , std::sort(ps+1,ps+1+n);
43     for(int i=1;i<=n;i++) bit.update(ps[i].y) , ret += i - bit.query(ps[i].y);
44     return ret;
45 }
46 
47 inline char nextchar() {
48     static const int BS = 1 << 21;
49     static char buf[BS],*st=buf+BS,*ed=buf+BS;
50     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
51     return st == ed ? -1 : *st++;
52 }
53 inline int getint() {
54     int ret = 0;
55     char ch;
56     while( !isdigit(ch=nextchar()) );
57     do ret=ret*10+ch-'0'; while( isdigit(ch=nextchar()) );
58     return ret;
59 }
60 
61 int main() {
62     n = getint();
63     for(int i=1;i<=n;i++) a[getint()] = i;
64     for(int i=1;i<=n;i++) b[getint()] = i;
65     for(int i=1;i<=n;i++) c[getint()] = i;
66     ans = calc(a,b) + calc(a,c) + calc(b,c);
67     ans = C(n) - ( ans >> 1 );
68     return printf("%lld\n",ans) , 0;
69 }
View Code

 

T3:
我能告诉你这题打表找规律可过?
我们考虑暴力找规律,发现二进制每一位被统计个数恰好为更低位(第0位为n/2)次数的一半,且上取整还是下取整与n-1在这位的值有关。于是我们就能AC了。
证明也很简单:
从边权低到高贪心。
考虑边权为2^0的边,差为1的点相互连接,这样的有n/2组,我们缩点。
考虑边权为2^1的边,差为2的点相互连接,这样的有n/2/2组,我们缩点。
以此类推即可。
代码:

 1 #include<bits/stdc++.h>
 2 typedef long long int lli;
 3 
 4 lli n,cur,ans;
 5 
 6 int main() {
 7     scanf("%lld",&n) , --n , cur = n;
 8     for(int i=0;n;n>>=1,i++) {
 9         if( ( cur = ( cur + ( n & 1 ) ) >> 1 ) & 1 ) ans ^= 1ll << i;
10     }
11     return printf("%lld\n",ans) , 0;
12 }
View Code

 

posted @ 2018-05-03 17:19  Cmd2001  阅读(312)  评论(0编辑  收藏  举报