20171226小测

于是今天上午有了一场愉悦的考试。
这里只是来写总结和题解的。

T1(中位数之塔):
链接:EZOJ_Alpha:P1018
一道找规律题,先二分答案然后在找规律线性时间验证。
显然先通过大小比较把输入转成0、1序列。
规律是什么呢?如果有两个连续的0或者1,则他们会每次向中间错一格,最后谁先到中间那么答案就是谁。
其实就是去比较距离。
如果两者均不存在,则最下面一行一定是01间隔的,手玩一下可发现规律。
然后我是怎么挂的呢?看出两个0上面全都是0,两个1上面全都是1,然后不会做,弃坑了。
交了30分暴力,然后数组开小,爆零啦QAQ。

然后上代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define debug cout
 6 using namespace std;
 7 const int maxn=1e5+1e2;
 8 
 9 int in[maxn<<1],nums[maxn<<1];
10 int n,dep;
11 
12 inline int findcon(int pos,int tar) {
13     int l = pos , r = pos;
14     while( l > 1 && ( nums[l]!=tar || nums[l-1]!=tar) )
15         --l;
16     while( r < ( n * 2 - 1 ) && ( nums[r]!=tar || nums[r+1]!=tar ) )
17         ++r;
18     return min( pos - l , r - pos );
19 }
20 inline void cov(int x) {
21     for(int i=1;i<n<<1;i++)
22         nums[i] = ( in[i] >= x );
23 }
24 inline bool judge(int x) {
25     cov(x);
26     int dze = findcon(n,0) , don = findcon(n,1);
27     if( dze != don )
28         return dze > don;
29     return ! ( (dep + nums[n] ) & 1 );
30 }
31 inline int getans() {
32     int ll = 1 , rr = ( n << 1 ) - 1 , mid;
33     while( rr != ll + 1 ) {
34         mid = ( ll + rr ) >> 1;
35         if( !judge(mid) )
36             rr = mid;
37         else ll = mid;
38     }
39     return ll;
40 }
41 
42 int main() {
43     scanf("%d",&n);
44     dep = ( n + 1 ) >> 1;
45     for(int i=1;i<n<<1;i++)
46         scanf("%d",in+i);
47     
48     printf("%d\n",getans());
49     
50     return 0;
51 }
View Code

 

T2(宝石迷阵):
链接:EZOJ_Alpha:P1017
让符合某种条件的东西最多,显然拆点网络流。然而如何保证90度转角?
考虑转了90度的两个点一定不在同一行,按行染色即可。
考场AC。

上代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=5e+3+1e2,maxm=maxn*50;
  9 const int inf=0x3f3f3f3f;
 10 
 11 int s[maxn],t[maxm],nxt[maxm],f[maxm];
 12 int dep[maxn];
 13 char in[55][55];
 14 int n,m,st,ed;
 15 
 16 inline void coredge(int from,int to,int flow) {
 17     static int cnt = 1;
 18     t[++cnt] = to,
 19     f[cnt] = flow,
 20     nxt[cnt] = s[from],
 21     s[from] = cnt;
 22 }
 23 inline void addedge(int from,int to,int flow) {
 24     coredge(from,to,flow);
 25     coredge(to,from,0);
 26 }
 27 
 28 inline bool bfs() {
 29     memset(dep,-1,sizeof(dep));
 30     dep[st] = 0;
 31     queue<int> q;
 32     q.push(st);
 33     while( q.size() ) {
 34         const int pos = q.front(); q.pop();
 35         for(int at=s[pos];at;at=nxt[at])
 36             if( f[at] && !~dep[t[at]] ) {
 37                 dep[t[at]] = dep[pos] + 1;
 38                 q.push(t[at]);
 39             }
 40     }
 41     return ~dep[ed];
 42 }
 43 inline int dfs(int pos,int flow) {
 44     if( pos == ed )
 45         return flow;
 46     int ret = 0 , now = 0;
 47     for(int at=s[pos];at;at=nxt[at])
 48         if( f[at] && dep[t[at]] > dep[pos] ) {
 49             now = dfs(t[at],min(flow,f[at]));
 50             ret += now , flow -= now,
 51             f[at] -= now , f[at^1] += now;
 52             if( !flow )
 53                 return ret;
 54         }
 55     if( !ret )
 56         dep[pos] = -1;
 57     return ret;
 58 }
 59 inline int dinic() {
 60     int ret = 0 , now = 0;
 61     while( bfs() ) {
 62         while( now = dfs(st,inf) )
 63             ret += now;
 64     }
 65     return ret;
 66 }
 67 
 68 inline int cov(int xx,int yy,int sta=0) { // 0 means full point or in point , 1 means out point.
 69     return ( ( xx - 1 ) * m + yy ) * 2 - 1 + sta;
 70 }
 71 inline bool judge(int xx,int yy) {
 72     return xx > 0 && xx <= n && yy > 0 && yy <= m && in[xx][yy]=='.';
 73 }
 74 inline void explain() {
 75     st = cov(n,m,1) + 1 , ed = cov(n,m,1) + 2;
 76     for(int i=1;i<=n;i++)
 77         for(int j=1;j<=m;j++)
 78             if( in[i][j] == '.' && ( ( i + j ) & 1 ) ) {
 79                 if( i & 1 )
 80                     addedge(st,cov(i,j),1);
 81                 else
 82                     addedge(cov(i,j),ed,1);
 83             }
 84     for(int i=1;i<=n;i++)
 85         for(int j=1;j<=m;j++)
 86             if( in[i][j] == '.' && ! ( ( i + j ) & 1 ) ) {
 87                 addedge(cov(i,j,0),cov(i,j,1),1);
 88                 if( i & 1 ) {
 89                     if( judge(i-1,j) )
 90                         addedge(cov(i,j,1),cov(i-1,j),1);
 91                     if( judge(i+1,j) )
 92                         addedge(cov(i,j,1),cov(i+1,j),1);
 93                     if( judge(i,j+1) )
 94                         addedge(cov(i,j+1),cov(i,j,0),1);
 95                     if( judge(i,j-1) )
 96                         addedge(cov(i,j-1),cov(i,j,0),1);
 97                 }
 98                 else {
 99                     if( judge(i-1,j) )
100                         addedge(cov(i-1,j),cov(i,j,0),1);
101                     if( judge(i+1,j) )
102                         addedge(cov(i+1,j),cov(i,j,0),1);
103                     if( judge(i,j+1) )
104                         addedge(cov(i,j,1),cov(i,j+1),1);
105                     if( judge(i,j-1) )
106                         addedge(cov(i,j,1),cov(i,j-1),1);
107                 }
108             }
109 }
110 
111 int main() {
112     scanf("%d%d",&n,&m);
113     for(int i=1;i<=n;i++)
114         scanf("%s",in[i]+1);
115     
116     explain();
117     
118     printf("%d\n",dinic());
119     
120     return 0;
121 }
View Code

 

T3(SiriusRen的卡牌):
链接:EZOJ_Alpha:P1016
首先先Orz一发SiriusRen,线段树巨佬(狂魔?)。
既然这样那么这道题就一定也是线段树了,考虑把一个属性a排序后枚举,那么对于ai小于now的i,我们需要在另外两个属性中选择一个更大;而ai大于now的i,我们需要两个属性均比他大。
用线段树维护另外两个属性(x,y)的关系,对于属性a比now小的i,(x,y)形成一个递降的阶梯。对于属性a比now大的i,对
他们的(x,y)连续取平均值形成两条线。我们对于now这个值的答案就是这些东西和(maxx,maxy)围成的面积。
线段树维护区间赋值即可。然而需要orz一发SiriusRen的写法:通过维护区间min和max简单地实现区间赋值。
我考场上怎么死的?推出来东西了,不会维护,最后28分暴力滚粗。

最后上代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lli long long int
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=5e5+1e2;
  9 //New operation learnt from RYC.
 10 
 11 struct SegmentTree {
 12     int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3];
 13     lli mxv[maxn<<3],miv[maxn<<3],sum[maxn<<3],lazy[maxn<<3];
 14     int cnt;
 15     
 16     inline void build(int pos,int ll,int rr) {
 17         l[pos] = ll , r[pos] = rr;
 18         if( ll == rr )
 19             return;
 20         const int mid = ( ll + rr ) >> 1;
 21         build(lson[pos]=++cnt,ll,mid);
 22         build(rson[pos]=++cnt,mid+1,rr);
 23     }
 24     inline void set(int pos,lli x) {
 25         mxv[pos] = miv[pos] = lazy[pos] = x;
 26         sum[pos] = x * ( r[pos] - l[pos] + 1 );
 27     }
 28     inline void push(int pos) {
 29         if( lazy[pos] ) {
 30             if( lson[pos] )
 31                 set(lson[pos],lazy[pos]);
 32             if( rson[pos] )
 33                 set(rson[pos],lazy[pos]);
 34             lazy[pos] = 0;
 35         }
 36     }
 37     inline void up(int pos) {
 38         sum[pos] = sum[lson[pos]] + sum[rson[pos]];
 39         mxv[pos] = max( mxv[lson[pos]] , mxv[rson[pos]] );
 40         miv[pos] = min( miv[lson[pos]] , miv[rson[pos]] );
 41     }
 42     inline void update(int pos,int ll,int rr,lli x) {
 43         if( rr < l[pos] || r[pos] < ll || x <= miv[pos] )
 44             return;
 45         if( ll <= l[pos] && r[pos] <= rr && x >= mxv[pos] ) {
 46             set(pos,x);
 47             return;
 48         }
 49         push(pos);
 50         update(lson[pos],ll,rr,x);
 51         update(rson[pos],ll,rr,x);
 52         up(pos);
 53     }
 54     inline lli full() {
 55         return sum[1];
 56     }
 57     inline lli query(int pos,int ll,int rr) {
 58         if( rr < l[pos] || r[pos] < ll )
 59             return 0;
 60         if( ll <= l[pos] && r[pos] <= rr )
 61             return sum[pos];
 62         push(pos);
 63         return query(lson[pos],ll,rr) + query(rson[pos],ll,rr);
 64     }
 65 }st;
 66 
 67 struct Node {
 68     int zz,xx,yy;
 69     friend bool operator < (const Node &a,const Node &b) {
 70         return a.zz < b.zz;
 71     }
 72 }ns[maxn];
 73 
 74 lli zz,xx,yy,ans;
 75 int n;
 76 
 77 inline void init() {
 78     sort(ns+1,ns+1+n);
 79     st.build(st.cnt=1,1,xx);
 80 }
 81 
 82 inline void getans() {
 83     for(int i=1;i<=n;i++)
 84         st.update(1,1,ns[i].xx,ns[i].yy);
 85     for(int i=zz,j=n;i;i--) {
 86         while( ns[j].zz == i ) {
 87             st.update(1,1,xx,ns[j].yy);
 88             st.update(1,1,ns[j].xx,yy);
 89             j--;
 90         }
 91         ans += xx * yy - st.query(1,1,xx);
 92     }
 93 }
 94 
 95 int main() {
 96     scanf("%d%lld%lld%lld",&n,&zz,&xx,&yy);
 97     for(int i=1;i<=n;i++)
 98         scanf("%d%d%d",&ns[i].zz,&ns[i].xx,&ns[i].yy);
 99     
100     init();
101     getans();
102     
103     printf("%lld\n",ans);
104     
105     return 0;
106 }
View Code

 

最后关于为什么我管这个OJ叫EZOJ_Alpha?
因为我曾经建立过一个局域网专用的基于HUSTOJ的EZOJ,上面有200+题,1k+评测记录,然后被我不小心rm -rf /*了......

posted @ 2017-12-26 20:35  Cmd2001  阅读(330)  评论(0编辑  收藏  举报