P6146 [USACO20FEB]Help Yourself G 题解

Posted Jerry_Jiang 的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P6146 [USACO20FEB]Help Yourself G 题解相关的知识,希望对你有一定的参考价值。

题目链接

先按左端点从小到大排序。

\\(f(i)\\) 表示前 \\(i\\) 条线段的所有子集的复杂度之和。

考虑从 \\(f(i-1)\\) 转移到 \\(f(i)\\),即考虑新加进来第 \\(i\\) 条线段的过程。第 \\(i\\) 条线段加进来所新产生的贡献分两种:

  1. 设除了第 \\(i\\) 条线段选中的线段集合为 \\(S\\),则若 \\(S\\) 中存在一条线段与第 \\(i\\) 条线段有交,即不产生新的复杂度。

  2. 反之,若 \\(S\\) 中所有线段都和 \\(i\\) 没有交(即 \\(\\forall j\\in S,r_j<l_i\\)),此时产生 \\(1\\) 的新复杂度。

容易推出第 \\(i\\) 条线段产生的复杂度为 \\(f(i-1)+2^cnt\\),其中 \\(cnt\\) 为第 \\(1\\sim i-1\\) 条线段中与第 \\(i\\) 条线段没有交的线段条数。所以 \\(f(i)=2f(i-1)+2^cnt\\)

计算 \\(cnt\\) 就在每个右端点处打个标记然后前缀和一下即可。

时间复杂度 \\(O(n\\log n)\\),瓶颈在排序。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,P=1e9+7;
int n,pre[N<<1],dp[N];
pii a[N];
int qpow(int x,int p)
	int res=1;
	while(p)
		if(p&1)
			res=1LL*res*x%P;
		
		x=1LL*x*x%P;
		p>>=1;
	
	return res;

int main()
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i].first,&a[i].second);
		pre[a[i].second]++;
	
	sort(a+1,a+n+1);
	for(int i=1;i<=n*2;i++)
		pre[i]+=pre[i-1];
	
	for(int i=1;i<=n;i++)
		dp[i]=(2LL*dp[i-1]%P+qpow(2,pre[a[i].first-1]))%P;
	
	printf("%d",dp[n]);
	return 0;

SPFA cojs 176. [USACO Feb07] 奶牛聚会

cojs 176. [USACO Feb07] 奶牛聚会

★☆   输入文件:sparty.in   输出文件:sparty.out   简单对比
时间限制:3 s   内存限制:16 MB

 

N(1 ≤ N ≤ 1000)个农场中的每个农场都有一只奶牛去参加位于第X个农场的聚会.共有M (1 ≤ M ≤ 100,000)条单向的道路,每条道路连接一对农场.通过道路i会花费Ti (1 ≤ Ti ≤ 100)的时间.

作为参加聚会的奶牛必须走到聚会的所在地(农场X).当聚会结束时,还要返回各自的农场.奶牛都是很懒的,她们想找出花费时间最少的路线.由于道路都是单向的,所有她们前往农场X的路线可能会不同于返程的路线.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back? 对于所有参加聚会的奶牛,找出前往聚会和返程花费总时间最多的奶牛,输出这只奶牛花费的总时间.


输入格式:

  • 第1行:三个用空格隔开的整数.

第2行到第M+1行,每行三个用空格隔开的整数:Ai, Bi,以及Ti.表示一条道路的起点,终点和需要花费的时间.


输出格式:

  • 唯一一行:一个整数: 所有参加聚会的奶牛中,需要花费总时间的最大值.

样例输出:

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

样例输入:

10

样例说明:

共有4只奶牛参加聚会,有8条路,聚会位于第2个农场.

第4只奶牛可以直接到聚会所在地(花费3时间),然后返程路线经过第1和第3个农场(花费7时间),总共10时间.

  1 #define N 100100
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5 #include<cstdio>
  6 int que[10000];
  7 int head1[1001],head2[1001];
  8 struct Edge{
  9     int v,last,w;
 10 }edge1[N],edge2[N];
 11 int t1=0,t2=0,n,m,x;
 12 int dis1[1001],dis2[1001],ans=0;
 13 void add_edge1(int u,int v,int w)
 14 {
 15     ++t1;
 16     edge1[t1].v=v;
 17     edge1[t1].w=w;
 18     edge1[t1].last=head1[u];
 19     head1[u]=t1;
 20 }
 21 void add_edge2(int u,int v,int w)
 22 {
 23     ++t2;
 24     edge2[t2].v=v;
 25     edge2[t2].w=w;
 26     edge2[t2].last=head2[u];
 27     head2[u]=t2;
 28 }
 29 void input()
 30 {
 31     scanf("%d%d%d",&n,&m,&x);
 32     for(int i=1;i<=m;++i)
 33     {
 34         int u,v,w;
 35         scanf("%d%d%d",&u,&v,&w);
 36         add_edge1(u,v,w);
 37         add_edge2(v,u,w);
 38     }
 39 }
 40 void SPFA1()
 41 {
 42     bool flag[1001]={0};
 43     memset(flag,false,sizeof(flag));
 44     int head=0,tail=0;
 45     que[++tail]=x;
 46     flag[x]=true;
 47     memset(dis1,99,sizeof(dis1));
 48     dis1[x]=0;
 49     while(head<tail)
 50     {
 51         ++head;
 52         int p=que[head];
 53         flag[p]=false;
 54         for(int l=head1[p];l;l=edge1[l].last)
 55         {
 56             if(dis1[edge1[l].v]>dis1[p]+edge1[l].w)
 57             {
 58                 dis1[edge1[l].v]=dis1[p]+edge1[l].w;
 59                 if(!flag[edge1[l].v])
 60                 {
 61                     ++tail;
 62                     que[tail]=edge1[l].v;
 63                     flag[edge1[l].v]=true;
 64                 }
 65                 
 66             }
 67         }
 68         
 69     }
 70 }
 71 void SPFA2()
 72 {
 73     bool flag[1001]={0};
 74     memset(flag,false,sizeof(flag));
 75     int head=0,tail=0;
 76     memset(que,0,sizeof(que));
 77     que[++tail]=x;
 78     flag[x]=true;
 79     memset(dis2,99,sizeof(dis2));
 80     dis2[x]=0;
 81     while(head<tail)
 82     {
 83         ++head;
 84         int p=que[head];
 85         flag[p]=false;
 86         for(int l=head2[p];l;l=edge2[l].last)
 87         {
 88             if(dis2[edge2[l].v]>dis2[p]+edge2[l].w)
 89             {
 90                 dis2[edge2[l].v]=dis2[p]+edge2[l].w;
 91                 if(!flag[edge2[l].v])
 92                 {
 93                     ++tail;
 94                     que[tail]=edge2[l].v;
 95                     flag[edge2[l].v]=true;
 96                 }
 97                 
 98             }
 99         }
100         
101     }
102 }
103 int main()
104 {
105     freopen("sparty.in","r",stdin);
106     freopen("sparty.out","w",stdout);
107     input();
108     SPFA1();
109     SPFA2();
110     for(int i=1;i<=n;++i)
111       ans=max(ans,dis1[i]+dis2[i]);
112     printf("%d\n",ans);
113     fclose(stdin);fclose(stdout);
114     return 0;
115 }

 

以上是关于P6146 [USACO20FEB]Help Yourself G 题解的主要内容,如果未能解决你的问题,请参考以下文章

题解[USACO20FEB]Equilateral Triangles P

[USACO11FEB] Cow Line

洛谷 P3014 [USACO11FEB]牛线Cow Line

P2857 [USACO06FEB]稳定奶牛分配Steady Cow Assignment

P4269 [USACO18FEB]Snow Boots G

JZYZOJ 1360 [usaco2011feb]人品问题 DP 树状数组 离散化