心得:
T1比较水,set水过,之前的有个达哥的等比数列的题,考场上忘了那道题怎么做了,虽然也做出来了
T2思路很好想,但分数十分玄学,(不考虑细节+数据很水+代码很菜=50分玄学分数)
T3很显然的dp,看着像一个单调队列,但也不怎么会,线段树学习一下其他人的打法
题解
T1
一个贪心,对于每个数要尽量往前放,才能使块数更少,用一个set记录在当前块里的序列,若当前处理的数放入后会不符合要求,那就set清空,重新搞
T2
一个比较显然的图论题,对于取并集的情况,那就是这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 */
WA0
建完双边还要考虑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 */
MLE60
如果用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 */
TLE50
然后就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 */
Accept
T3
很神奇的堆优化
$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 }
原文地址:https://www.cnblogs.com/casun547/p/11376351.html
时间: 2024-10-12 06:50:21