2018.8.8 Noip2018模拟测试赛(二十一)

日期:

八月七号

 总分:

300分

 难度:

提高 ~ 省选  

 得分:

112分(OvO)

题目目录:

  T1:幸福的道路

  T2:Solitaire

  T3:Flags

赛后心得:

第一题裸树d啊!竟然花了一个多小时才切掉……

第二题输出样例成功骗到12分。

题解:

T1:幸福的道路

树形dp,先两次dfs算出每个点的最长路,用两个单调队列维护每天的极差……做完了……

CODE:

 1 #include<iostream>
 2 #include<queue>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 int n,m,x,tot=0,h[1000005];
 8 long long y,f[1000005],g[1000005],a[1000005];
 9 struct Edge{
10     int x,next;
11     long long dis;
12 }e[2000005];
13 int q1[1000005],q2[1000005];
14 
15 inline void add_edge(int x,int y,long long z){
16     e[++tot].x=y,e[tot].dis=z;
17     e[tot].next=h[x],h[x]=tot;
18 }
19 
20 void dfs1(int x,int fa){
21     for(int i=h[x];i;i=e[i].next){
22         if(e[i].x==fa)continue;
23         dfs1(e[i].x,x);
24         f[x]=max(f[x],f[e[i].x]+e[i].dis);
25     }
26 }
27 
28 void dfs2(int x,int fa){
29     long long maxn=0,sec=0;
30     for(int i=h[x];i;i=e[i].next){
31         if(e[i].x==fa)continue;
32         if(f[e[i].x]+e[i].dis>maxn)
33             sec=maxn,maxn=f[e[i].x]+e[i].dis;
34         else sec=max(sec,f[e[i].x]+e[i].dis);
35         g[e[i].x]=g[x]+e[i].dis;
36     }
37     for(int i=h[x];i;i=e[i].next){
38         if(e[i].x==fa)continue;
39         if(f[e[i].x]+e[i].dis==maxn)
40             g[e[i].x]=max(g[e[i].x],sec+e[i].dis);
41         else g[e[i].x]=max(g[e[i].x],maxn+e[i].dis);
42         dfs2(e[i].x,x);
43     }
44 }
45 
46 int main(){
47     scanf("%d%d",&n,&m);
48     for(int i=2;i<=n;i++){
49         scanf("%d%lld",&x,&y);
50         add_edge(i,x,y);
51         add_edge(x,i,y);
52     }
53     dfs1(1,-1),dfs2(1,-1);
54     for(int i=1;i<=n;i++)a[i]=max(f[i],g[i]);
55     int l1=1,l2=1,r1=0,r2=0,tmp=0,ans=0;;
56     for(int i=1;i<=n;i++){
57         while(l1<=r1&&a[i]<=a[q1[r1]])r1--;
58         while(l2<=r2&&a[i]>=a[q2[r2]])r2--;
59         q1[++r1]=i,q2[++r2]=i;
60         if(a[q2[l2]]-a[q1[l1]]>m){
61             if(q2[l2]<=q1[l1])tmp=q2[l2],l2++;
62             else tmp=q1[l1],l1++;
63         }
64         ans=max(ans,i-tmp);
65     }
66     printf("%d",ans);
67 }

T2:Solitaire

 题解戳这里

CODE:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4  
 5 #define mod 1000000007
 6 int n,k,ans,f[2005][2005],sum[2005];
 7  
 8 int main(){
 9     scanf("%d%d",&n,&k);
10     f[0][n+1]=1;
11     for(int i=1;i<=k;i++)
12         for(int j=n+1;j>=1;j--){
13             sum[j]=(sum[j+1]+f[i-1][j])%mod;
14             f[i][j]=(j<=n-i+1?sum[j]:0);
15         }
16     ans=(f[k][1]-f[k-1][1]+mod)%mod;
17     for(int i=1;i<=n-k-1;i++)ans=(ans+ans)%mod;
18     printf("%d",ans);
19 }

T3:Flags

2-sat 问题

题解戳这里

CODE:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<stack>
  4 #include<algorithm>
  5 #include<cstring>
  6 using namespace std;
  7 
  8 int v[100005];
  9 int n,x,y,tot=0,h[100005];
 10 int scc[100005],dfn[100005],low[100005],C,cnt;
 11 bool vis[100005];
 12 struct Edge{
 13     int x,next;
 14 }e[5000000];
 15 pair<int,int> a[20005];
 16 stack<int> s;
 17 
 18 inline void add_edge(int x,int y){
 19     e[++tot].x=y;
 20     e[tot].next=h[x],h[x]=tot;
 21 }
 22 
 23 void tarjan(int x){
 24     dfn[x]=low[x]=++cnt;
 25     s.push(x),vis[x]=true;
 26     for(int i=h[x];~i;i=e[i].next){
 27         if(!dfn[e[i].x]){
 28             tarjan(e[i].x),low[x]=min(low[x],low[e[i].x]);
 29         }else if(vis[e[i].x]){
 30             low[x]=min(low[x],dfn[e[i].x]);
 31         }   
 32     }
 33     if(dfn[x]==low[x]){
 34         C++;
 35         int tmp;
 36         for(;;){
 37             tmp=s.top();
 38             vis[tmp]=false,scc[tmp]=C;
 39             s.pop();
 40             if(tmp==x)break;
 41         }
 42     }
 43 }
 44 
 45 void build(int o,int l,int r){
 46     if(r-l==1){
 47         add_edge(o+n*2,a[l].second^1);
 48         return;
 49     }
 50     add_edge(o+n*2,(o<<1)+n*2);
 51     add_edge(o+n*2,(o<<1|1)+n*2);
 52     int mid=l+r>>1;
 53     build(o<<1,l,mid),build(o<<1|1,mid,r);
 54 }
 55 
 56 void link(int o,int l,int r,int x,int y,int a){
 57     if(l>=x&&r<=y){
 58         add_edge(a,o+n*2);
 59         return;
 60     }
 61     int mid=l+r>>1;
 62     if(x<mid)link(o<<1,l,mid,x,y,a);
 63     if(y>mid)link(o<<1|1,mid,r,x,y,a);
 64 }
 65 
 66 inline pair<int,int> get(int x,int len){
 67     int l=0,r=x;
 68     pair<int,int> ans;
 69     while(l<r){
 70         int mid=l+r>>1;
 71         if(a[x].first-a[mid].first<len)r=mid;
 72         else l=mid+1;
 73     }
 74     ans.first=l;
 75     l=x,r=n*2-1;
 76     while(l<r){
 77         int mid=l+r+1>>1;
 78         if(a[mid].first-a[x].first<len)l=mid;
 79         else r=mid-1;
 80     }
 81     ans.second=l;
 82     return ans;
 83 }
 84 
 85 inline bool check(int d){
 86     memset(scc,0,sizeof(scc));
 87     memset(dfn,0,sizeof(dfn));
 88     memset(low,0,sizeof(low));
 89     memset(h,-1,sizeof(h)),tot=0;
 90     build(1,0,n*2);
 91     for(int i=0;i<n*2;i++){
 92         int id=a[i].second;
 93         pair<int,int> x=get(i,d);
 94         if(i<x.second)link(1,0,n*2,i+1,x.second+1,id);
 95         if(x.first<i)link(1,0,n*2,x.first,i,id);
 96     }
 97     C=cnt=0;
 98     for(int i=0;i<n*2;i++)if(!dfn[i])tarjan(i);
 99     for(int i=0;i<n*2;i++)
100         if(scc[a[i].second]==scc[a[i].second^1])return false;
101     return true;
102 }
103 
104 int main(){
105     scanf("%d",&n);
106     for(int i=0;i<n;i++){
107         scanf("%d%d",&x,&y);
108         a[2*i+1]=make_pair(x,2*i+1);
109         a[2*i]=make_pair(y,2*i);
110     }
111     sort(a,a+n*2);
112     int l=0,r=1000000000;
113     while(l<r){
114         int mid=l+r+1>>1;
115         if(check(mid))l=mid;
116         else r=mid-1;
117     }
118     printf("%d",l);
119 }
posted @ 2018-08-12 20:48  ezoiLZH  阅读(266)  评论(0编辑  收藏  举报