标签:一个 pre gif 转移 size 线段 == friend 不能
T1比较水,set水过,之前的有个达哥的等比数列的题,考场上忘了那道题怎么做了,虽然也做出来了
T2思路很好想,但分数十分玄学,(不考虑细节+数据很水+代码很菜=50分玄学分数)
T3很显然的dp,看着像一个单调队列,但也不怎么会,线段树学习一下其他人的打法
一个贪心,对于每个数要尽量往前放,才能使块数更少,用一个set记录在当前块里的序列,若当前处理的数放入后会不符合要求,那就set清空,重新搞
一个比较显然的图论题,对于取并集的情况,那就是这k个点向新点连边
取交集的话是从新点向这k个点连边,
但还要注意k==1时建双边,否则就会WA 0(理论上)
1 //连有向边,<u,v>u信息在v中有,查询时就是看u能不能到v
2 #include<iostream>
3 #include<cstdio>
4 #include<cstring>
5 #include<cmath>
6 #include<cstdlib>
7 #include<set>
8 #define R register
9 using namespace std;
10 inline int read()
11 {
12 int f=1,x=0;char ch=getchar();
13 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
14 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
15 return x*f;
16 }
17 const int maxn=1000000;
18 struct node{
19 int v,nxt;
20 }e[maxn*2];int h[maxn],nu;
21 void add(int x,int y)
22 {
23 e[++nu].v=y;
24 e[nu].nxt=h[x];
25 h[x]=nu;
26 }
27 int v[maxn];
28 int dfs(int nw,int to)//环???
29 {
30 v[nw]=1;
31 if(nw==to)return 1;
32 for(int i=h[nw];i;i=e[i].nxt)
33 {
34 int y=e[i].v;
35 if(v[y])continue;
36 if(dfs(y,to))return 1;
37 }
38 return 0;
39 }
40 int main()
41 {
42 // freopen("data","r",stdin);
43 int tot=read(),m=read();
44 while(m--)
45 {
46 int opt=read();
47 if(opt)
48 {
49 int x=read(),y=read();
50 memset(v,0,sizeof v);
51 printf("%d\n",dfs(x,y));
52 }
53 else
54 {
55 int mot=read(),k=read();
56 tot++;
57 if(mot)
58 {
59 for(int i=1;i<=k;++i)
60 {
61 int x=read();
62 add(x,tot);
63 }
64 }
65 else
66 {
67 for(int i=1;i<=k;++i)
68 {
69 int x=read();
70 add(tot,x);
71 }
72 }
73 }
74 }
75 }
76 /*
77 g++ 2.cpp -o 2
78 ./2
79
80 */
建完双边还要考虑dfs不能死循环,否则MLE60(dfs爆栈)
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<set>
7 #define R register
8 using namespace std;
9 inline int read()
10 {
11 int f=1,x=0;char ch=getchar();
12 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
13 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14 return x*f;
15 }
16 const int maxn=1000000;
17 struct node{
18 int v,nxt;
19 }e[maxn*2];int h[maxn],nu;
20 void add(int x,int y)
21 {
22 e[++nu].v=y;
23 e[nu].nxt=h[x];
24 h[x]=nu;
25 }
26 int dfs(int nw,int to)
27 {
28 if(nw==to)return 1;
29 for(int i=h[nw];i;i=e[i].nxt)
30 {
31 int y=e[i].v;
32 if(dfs(y,to))return 1;
33 }
34 return 0;
35 }
36 int main()
37 {
38 // freopen("data","r",stdin);
39 int tot=read(),m=read();
40 while(m--)
41 {
42 int opt=read();
43 if(opt)
44 {
45 int x=read(),y=read();
46 printf("%d\n",dfs(x,y));
47 }
48 else
49 {
50 int mot=read(),k=read();
51 tot++;
52 if(mot)
53 {
54 for(int i=1;i<=k;++i)
55 {
56 int x=read();
57 add(x,tot);
58 if(k==1)add(tot,x);
59 }
60 }
61 else
62 {
63
64 for(int i=1;i<=k;++i)
65 {
66 int x=read();
67 add(tot,x);
68 if(k==1)add(x,tot);
69 }
70 }
71 }
72 }
73 }
74 /*
75 g++ 2.cpp -o 2
76 ./2
77
78 */
如果用vis数组标记且每次memset,TLE50
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<set>
7 #define R register
8 using namespace std;
9 inline int read()
10 {
11 int f=1,x=0;char ch=getchar();
12 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
13 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14 return x*f;
15 }
16 const int maxn=800000;
17 struct node{
18 int v,nxt;
19 }e[maxn];int h[maxn],nu;
20 void add(int x,int y)
21 {
22 e[++nu].v=y;
23 e[nu].nxt=h[x];
24 h[x]=nu;
25 }
26 int v[maxn];
27 int dfs(int nw,int to)
28 {
29 v[nw]=1;
30 if(nw==to)return 1;
31 for(int i=h[nw];i;i=e[i].nxt)
32 {
33 int y=e[i].v;
34 if(v[y])continue;
35 if(dfs(y,to))return 1;
36 }
37 return 0;
38 }
39 int main()
40 {
41 // freopen("data","r",stdin);
42 int tot=read(),m=read();
43 while(m--)
44 {
45 int opt=read();
46 if(opt)
47 {
48 int x=read(),y=read();
49 memset(v,0,sizeof v);
50 printf("%d\n",dfs(x,y));
51 }
52 else
53 {
54 int mot=read(),k=read();
55 tot++;
56 if(mot)
57 {
58 for(int i=1;i<=k;++i)
59 {
60 int x=read();
61 add(x,tot);
62 if(k==1)add(tot,x);
63 }
64 }
65 else
66 {
67
68 for(int i=1;i<=k;++i)
69 {
70 int x=read();
71 add(tot,x);
72 if(k==1)add(x,tot);
73 }
74 }
75 }
76 }
77 }
78 /*
79 g++ 2.cpp -o 2
80 ./2
81
82 */
然后就A了
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<set>
7 #define R register
8 using namespace std;
9 inline int read()
10 {
11 int f=1,x=0;char ch=getchar();
12 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
13 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14 return x*f;
15 }
16 const int maxn=800000;
17 struct node{
18 int v,nxt;
19 }e[maxn];int h[maxn],nu;
20 void add(int x,int y)
21 {
22 e[++nu].v=y;
23 e[nu].nxt=h[x];
24 h[x]=nu;
25 }
26 int dfs(int nw,int f,int to)
27 {
28 if(nw==to)return 1;
29 for(int i=h[nw];i;i=e[i].nxt)
30 {
31 int y=e[i].v;
32 if(y==f)continue;
33 if(dfs(y,nw,to))return 1;
34 }
35 return 0;
36 }
37 int main()
38 {
39 // freopen("data","r",stdin);
40 int tot=read(),m=read();
41 while(m--)
42 {
43 int opt=read();
44 if(opt)
45 {
46 int x=read(),y=read();
47 printf("%d\n",dfs(x,0,y));
48 }
49 else
50 {
51 int mot=read(),k=read();
52 tot++;
53 if(mot)
54 {
55 for(int i=1;i<=k;++i)
56 {
57 int x=read();
58 add(x,tot);
59 if(k==1)add(tot,x);
60 }
61 }
62 else
63 {
64
65 for(int i=1;i<=k;++i)
66 {
67 int x=read();
68 add(tot,x);
69 if(k==1)add(x,tot);
70 }
71 }
72 }
73 }
74 }
75 /*
76 g++ 2.cpp -o 2
77 ./2
78
79 */
很神奇的堆优化
$f[i]=min{f[j]+max(sum[i]-sum[j],b[j])}(i-k<=j<i)$
那么转移的时候只需要考虑当前$f[j]+b[j]$和$f[j]-sum[j]$(j不一定相同,但要符合范围)中的最小值,
所以分别存入堆中,第一个堆存f[j]+b[j],第二个存f[j]-sum[j],
找到当前合法两个队顶的元素x1,x2,f[i]=min{x1,x2+sum[i]}
那怎么处理对于每个j的max的问题?
对于每个点先放第一个堆,
在取第一个队顶元素的时候,若f[j]+b[j]<f[j]-sum[j]+sum[i],那就pop第一个堆,并放入第二个堆
然后就可以愉快地解决了,当然还要先往堆中放一个极大值
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<set>
7 #include<queue>
8 #define INF 0x7ffffffffffffff
9 #define ll long long
10 #define R register
11 using namespace std;
12 inline int read()
13 {
14 int f=1,x=0;char ch=getchar();
15 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
16 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
17 return x*f;
18 }
19 const int maxn=500005;
20 inline ll min(ll x,ll y){return x<y?x:y;}
21 inline ll max(ll x,ll y){return x<y?y:x;}
22 int n,k;
23 int a[maxn],b[maxn],sum[maxn];ll f[maxn];
24 struct node{
25 ll da;
26 int id;
27 bool friend operator < (node x,node y){
28 return x.da>y.da;
29 }
30 };
31 priority_queue<node>q1;
32 priority_queue<node>q2;
33 int main()
34 {
35 n=read(),k=read();
36 for(R int i=1;i<=n;++i){
37 a[i]=read(),
38 sum[i]=sum[i-1]+a[i];
39 f[i]=INF;
40 }
41 for(R int i=0;i<n;++i)
42 b[i]=read();
43 f[0]=0;
44 node t;t.id=0,t.da=f[0]+b[0];
45 q1.push(t);
46 t.da=INF,t.id=n+1;
47 q1.push(t);
48 q2.push(t);
49 for(R int i=1;i<=n;++i)
50 {
51 node t1=q1.top();
52 int j=t1.id;
53 while(q1.size()&&(j<i-k||t1.da<f[j]-sum[j]+sum[i])){
54 if(t1.da<f[j]-sum[j]+sum[i]){
55 node t;t.id=j,t.da=f[j]-sum[j];
56 q2.push(t);
57 }
58 q1.pop();
59 t1=q1.top();j=t1.id;
60 }
61 node t2=q2.top();
62 while(q1.size()&&t2.id<i-k)q2.pop(),t2=q2.top();
63 f[i]=min(t1.da,t2.da+sum[i]);
64 node t;t.da=f[i]+b[i],t.id=i;
65 q1.push(t);
66 }
67 printf("%lld\n",f[n]);
68 }
标签:一个 pre gif 转移 size 线段 == friend 不能
原文地址:https://www.cnblogs.com/casun547/p/11376351.html