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 }