2017/07/25 杂题(完全不可做题(划去))选讲
Posted Loser Of Life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017/07/25 杂题(完全不可做题(划去))选讲相关的知识,希望对你有一定的参考价值。
先膜一发主讲人@Antileaf
真是核平的一天那……大脑已经被蹂躏的死去活来了……
cogs2421 简单的Treap
链接:http://cogs.pro/cogs/problem/problem.php?pid=2421
题意:什么都给你了,建出Treap,输出先序遍历顺序。
实际上只是用了Treap的原则建树……先按照数值大小排序,然后按照建立笛卡尔树方法,维护单调栈,最大的全扔到右儿子去即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=500005; 7 int n,lc[maxn],rc[maxn],stack[maxn],top,root; 8 struct node 9 { 10 int val,fix; 11 bool operator <(const node b)const{ 12 return val<b.val; 13 } 14 }a[maxn]; 15 void dfs(int root) 16 { 17 printf("%d ",a[root].val); 18 if(lc[root])dfs(lc[root]); 19 if(rc[root])dfs(rc[root]); 20 } 21 int main() 22 { 23 freopen("treap.in","r",stdin); 24 freopen("treap.out","w",stdout); 25 int __size__=128<<20; 26 char *__p__=(char*)malloc(__size__)+__size__; 27 __asm__("movl %0, %%esp\\n"::"r"(__p__)); 28 scanf("%d",&n); 29 for(int i=1;i<=n;i++)scanf("%d",&a[i].val); 30 for(int i=1;i<=n;i++)scanf("%d",&a[i].fix); 31 sort(a+1,a+n+1); 32 for(int i=1;i<=n;i++) 33 { 34 stack[top+1]=0; 35 while(top&&a[stack[top]].fix>a[i].fix)top--; 36 lc[i]=stack[top+1]; 37 (top?rc[stack[top]]:root)=i; 38 stack[++top]=i; 39 } 40 dfs(root); 41 }
cogs2434 暗之链锁
链接:http://cogs.pro/cogs/problem/problem.php?pid=2434
题意:一个图由一棵树和m条副边形成,只能砍一条树边、一条副边,问有多少种方法使原图不连通。
树上差分啊……找到每条副边,差分处理,然后对每条树边考虑被几条副边覆盖,$x=0$时有m种,$x=1$时就一种。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 const int maxn=100005,maxm=200005; 8 vector<int>G[maxn],q[maxn]; 9 int n,m,prt[maxn],anc[maxn],a[maxn],x,y,ans; 10 bool vis[maxn]; 11 int findroot(int x) 12 { 13 return anc[x]==x?x:(anc[x]=findroot(anc[x])); 14 } 15 void dfs1(int x) 16 { 17 int cnt=G[x].size(); 18 anc[x]=x; 19 for(int i=0;i<cnt;i++) 20 if(G[x][i]!=prt[x]) 21 { 22 prt[G[x][i]]=x; 23 dfs1(G[x][i]); 24 } 25 vis[x]=1;cnt=q[x].size(); 26 for(int i=0;i<cnt;i++) 27 if(vis[q[x][i]])a[findroot(q[x][i])]-=2; 28 anc[x]=prt[x]; 29 } 30 void dfs2(int x) 31 { 32 int cnt=G[x].size();anc[x]=x; 33 for(int i=0;i<cnt;i++) 34 if(G[x][i]!=prt[x]) 35 { 36 dfs2(G[x][i]); 37 a[x]+=a[G[x][i]]; 38 } 39 if(prt[x]) 40 if(!a[x])ans+=m; 41 else if(a[x]==1)ans++; 42 } 43 int haha() 44 { 45 freopen("yam.in","r",stdin); 46 freopen("yam.out","w",stdout); 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<n;i++) 49 { 50 scanf("%d%d",&x,&y); 51 G[x].push_back(y);G[y].push_back(x); 52 } 53 for(int i=0;i<m;i++) 54 { 55 scanf("%d%d",&x,&y); 56 if(x==y)continue; 57 a[x]++;a[y]++; 58 q[x].push_back(y),q[y].push_back(x); 59 } 60 dfs1(1);dfs2(1); 61 printf("%d\\n",ans); 62 //while(1); 63 } 64 int sb=haha(); 65 int main(){;}
HEOI2017 组合数问题
挖坑……
NOI2016区间
链接:http://cogs.pro/cogs/problem/problem.php?pid=2406
题意:数轴上有n个闭区间,求出m个区间,使至少1个点被这些区间全部包括,并最小化最大区间长度与最小区间长度之差。
真是妙啊……首先对区间按长度排序,对坐标离散化,随后,动态增减区间,线段树动态维护。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 const int maxn=1000005; 7 int n,m,x,sm[maxn<<2],mx[maxn<<2],b[maxn],p[maxn],cnt; 8 struct districts 9 { 10 int l,r,len; 11 }ques[maxn]; 12 int cmp(const int &a,const int &b) 13 { 14 return ques[a].len<ques[b].len; 15 } 16 #define mid ((l+r)>>1) 17 #define lson root<<1,l,mid 18 #define rson root<<1|1,mid+1,r 19 #define lc root<<1 20 #define rc root<<1|1 21 void Modify(int root,int l,int r,int L,int R,int val) 22 { 23 if(L<=l&&r<=R) 24 { 25 mx[root]+=val; 26 sm[root]+=val; 27 return; 28 } 29 if(mid>=L)Modify(lson,L,R,val); 30 if(mid<R)Modify(rson,L,R,val); 31 mx[root]=max(mx[lc],mx[rc])+sm[root]; 32 } 33 int haha() 34 { 35 freopen("interval.in","r",stdin); 36 freopen("interval.out","w",stdout); 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=n;i++) 39 { 40 p[i]=i;districts &d=ques[i]; 41 scanf("%d%d",&d.l,&d.r); 42 d.len=d.r-d.l+1; 43 b[++cnt]=d.l;b[++cnt]=d.r; 44 } 45 sort(p+1,p+n+1,cmp);sort(b+1,b+cnt+1); 46 cnt=unique(b+1,b+cnt+1)-b-1; 47 for(int i=1;i<=n;i++) 48 { 49 int t=p[i];districts &d=ques[t]; 50 d.l=lower_bound(b+1,b+cnt+1,d.l)-b; 51 d.r=lower_bound(b+1,b+cnt+1,d.r)-b; 52 } 53 int ans=0x7f7f7f7f; 54 for(int i=1,j=0;j<n||(mx[1]==m&&j==n);) 55 { 56 while(mx[1]<m&&j<n) 57 { 58 j++; 59 Modify(1,1,cnt,ques[p[j]].l,ques[p[j]].r,1); 60 } 61 while(mx[1]==m&&i<=n) 62 { 63 ans=min(ans,ques[p[j]].len-ques[p[i]].len); 64 Modify(1,1,cnt,ques[p[i]].l,ques[p[i]].r,-1); 65 i++; 66 } 67 } 68 if(ans==0x7f7f7f7f)ans=-1; 69 printf("%d\\n",ans); 70 } 71 int sb=haha(); 72 int main(){;}
ZJOI2004 树的果实
挖坑……
HNOI2016 序列
挖坑……
cogs2582 动物城的鸳鸯蛋传说
链接:http://cogs.pro/cogs/problem/problem.php?pid=2582
题意:有两个数列,问用第一个数列能组出第二个数列中哪些数。
bitset第一题……
1 http://cogs.pro/cogs/problem/problem.php?pid=2582
cogs2089 平凡的测试数据
出门左转:http://www.cnblogs.com/Loser-of-Life/p/7236695.html
cogs1000 伊吹萃香
出门左转:http://www.cnblogs.com/Loser-of-Life/p/7237419.html
NOI2014 起床困难综合症
链接:http://cogs.pro/cogs/problem/problem.php?pid=1684
题意:一路位运算,求最大攻击伤害。
对每一位进行处理,在m范围内能大伤害就大伤害,相同就在这一位取0。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int haha() 7 { 8 freopen("sleep.in","r",stdin); 9 freopen("sleep.out","w",stdout); 10 int n,m;scanf("%d%d",&n,&m); 11 int id,ide=0;for(id=1;id<m;id=id<<1|1); 12 for(int i=1;i<=n;i++) 13 { 14 char opt[5];int v;scanf("%s%d",opt,&v); 15 switch(opt[0]) 16 { 17 case \'O\':ide|=v;id|=v;break; 18 case \'X\':ide^=v;id^=v;break; 19 case \'A\':ide&=v;id&=v;break; 20 } 21 } 22 bool judge=0;int q=0; 23 for(int i=29;i>=0;i--) 24 { 25 int t=ide>>i&1; 26 if((judge||(m>>i&1))&&(id>>i&1)>t)t=id>>i&1; 27 if(m>>i&1)judge=1; 28 q|=t<<i; 29 } 30 printf("%d\\n",q); 31 } 32 int sb=haha(); 33 int main(){;}
cogs2235 烤鸡翅
出门左转:http://www.cnblogs.com/Loser-of-Life/p/7236721.html
HEOI2017 期末考试
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4868
题意:有一些人等成绩,每超过预期一天会增加学生不满度,减少判卷时间会增加老师不满度(⊙﹏⊙)b……求最低总不满度。
通过一顿乱搞可以得出总不满度关于时间的函数是一个严格的凹函数,三分时间,求最小值水之。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int maxn=100005; 8 int A,B,C;int n,m,t[maxn],b[maxn]; 9 LL work(int val) 10 { 11 LL res=0,v1=0,v2=0; 12 for(int i=1;i<=n;i++) 13 if(val>t[i])res+=(LL)(val-t[i])*C; 14 for(int i=1;i<=m;i++) 15 if(b[i]<val)v1+=val-b[i]; 16 else v2+=b[i]-val; 17 if(A>=B)res+=(LL)v2*B; 18 else 19 { 20 res+=(LL)min(v1,v2)*A; 21 if(v1<v2) res+=(LL)(v2-v1)*B; 22 } 23 return res; 24 } 25 int haha() 26 { 27 scanf("%d%d%d",&A,&B,&C); 28 scanf("%d%d",&n,&m); 29 int maxx=0; 30 for(int i=1;i<=n;i++)scanf("%d",&t[i]); 31 for(int i=1;i<=m;i++)scanf("%d",&b[i]); 32 int l=0,r=100000; 33 LL ans=1e18; 34 while(r-l>5) 35 { 36 int mid=l+(r-l)/3,midmid=r-(r-l)/3; 37 LL v1=work(mid),v2=work(midmid); 38 if(v1<=v2) 39 { 40 ans=min(ans,v1); 41 r=midmid; 42 } 43 else 44 { 45 ans=min(ans,v2); 46 l=mid; 47 } 48 } 49 for(int i=l;i<=r;i++)ans=min(ans,work(i)); 50 printf("%lld\\n",ans); 51 } 52 int sb=haha(); 53 int main(){;}
51nod1597 有限背包计数问题
挖坑……
cogs1825 道路和航线
链接:http://cogs.pro/cogs/problem/problem.php?pid=1825
题意:一张带权混合图,保证无向边权值非负,有向边保证不会带来环,求1号节点到所有节点最短路。
我们知道,非负权图可以用Dijkstra保证时间复杂度在$O(nlogn)$,而有向图可以用记忆化搜索保证线性时间复杂度。那么想法就出现了:将每一个无向图中连通块缩成一个点,再进行记忆化搜索。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 const int maxt=25005,maxr=50005; 9 struct node 10 { 11 int from,to,weight,next; 12 }edge1[maxr<<1]; 13 int head1[maxt],tot,t,r,p,s,cnt; 14 void addedge1(int u,int v,int w) 15 { 16 edge1[++tot]=(node){u,v,w,head1[u]};head1[u]=tot; 17 } 18 vector<int>a[maxt]; 19 int id[maxt]; 20 void dfs1(int x) 21 { 22 id[x]=cnt;a[cnt].push_back(x); 23 for(int i=head1[x];i;i=edge1[i].next) 24 if(!id[edge1[i].to])dfs1(edge1[i].to); 25 } 26 vector<int>G[maxt],W[maxt],G2[maxt]; 27 int entrance_degree[maxr]; 28 bool vis[maxr]; 29 void dfs2(int x) 30 { 31 vis[x]=1; 32 for(int i=0;i<G2[x].size();i++) 33 { 34 entrance_degree[G2[x][i]]++; 35 if(!vis[G2[x][i]])dfs2(G2[x][i]); 36 } 37 } 38 struct point 39 { 40 int dis,id; 41 bool operator <(const point &b)const{ 42 return dis>b.dis; 43 } 44 }; 45 priority_queue<point>heap; 46 int dist[maxt]; 47 void Dijkstra() 48 { 49 while(!heap.empty()) 50 { 51 point tmp=heap.top();heap.pop(); 52 int dis=tmp.dis,iden=tmp.id; 53 if(vis[iden])continue; 54 vis[iden]=1; 55 for(int i=head1[iden];i;i=edge1[i].next) 56 { 57 int v=edge1[i].to; 58 if(dist[v]>dist[iden]+edge1[i].weight) 59 2021年11月的做题记录