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
"::"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 }
cogs2421

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
",ans);
62     //while(1);
63 }
64 int sb=haha();
65 int main(){;}
cogs2434

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
",ans);
70 }
71 int sb=haha();
72 int main(){;}
cogs2406

ZJOI2004 树的果实

挖坑……

HNOI2016 序列

挖坑……

cogs2582 动物城的鸳鸯蛋传说

链接:http://cogs.pro/cogs/problem/problem.php?pid=2582

题意:有两个数列,问用第一个数列能组出第二个数列中哪些数。

bitset第一题……

1 http://cogs.pro/cogs/problem/problem.php?pid=2582
cogs2582

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
",q);
31 }
32 int sb=haha();
33 int main(){;}
cogs1684

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
",ans);
51 }
52 int sb=haha();
53 int main(){;}
bzoj4869

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             {
 60                 dist[v]=dist[iden]+edge1[i].weight;
 61                 heap.push((point){dist[v],v});
 62             }
 63         }
 64     }
 65 }
 66 void bfs()
 67 {
 68     memset(vis,0,sizeof(vis));
 69     memset(dist,63,sizeof(dist));
 70     queue<int>q;q.push(id[s]);dist[s]=0;
 71     while(!q.empty())
 72     {
 73         int x=q.front();q.pop();
 74         for(int i=0;i<a[x].size();i++)
 75             if(dist[a[x][i]]<0x3f3f3f3f)heap.push((point){dist[a[x][i]],a[x][i]});
 76         Dijkstra();
 77         for(int i=0;i<a[x].size();i++)
 78             for(int j=0;j<G[a[x][i]].size();j++)
 79             {
 80                 dist[G[a[x][i]][j]]=min(dist[G[a[x][i]][j]],dist[a[x][i]]+W[a[x][i]][j]);
 81                 if(!--entrance_degree[id[G[a[x][i]][j]]])q.push(id[G[a[x][i]][j]]);
 82             }
 83     }
 84 }
 85 int haha()
 86 {
 87     freopen("roadplane.in","r",stdin);
 88     freopen("roadplane.out","w",stdout);
 89     scanf("%d%d%d%d",&t,&r,&p,&s);
 90     for(int i=1;i<=r;i++)
 91     {
 92         int u,v,w;scanf("%d%d%d",&u,&v,&w);
 93         addedge1(u,v,w);addedge1(v,u,w);
 94     }
 95     for(int i=1;i<=t;i++)
 96         if(!id[i])
 97         {
 98             cnt++;
 99             dfs1(i);
100         }
101     for(int i=1;i<=p;i++)
102     {
103         int x,y,z;scanf("%d%d%d",&x,&y,&z);
104         G[x].push_back(y);
105         W[x].push_back(z);
106         G2[id[x]].push_back(id[y]);
107     }
108     dfs2(id[s]);
109     bfs();
110     for(int i=1;i<=t;i++)
111         if(dist[i]==0x3f3f3f3f)puts("NO PATH");
112         else printf("%d
",dist[i]);
113 }
114 int sb=haha();
115 int main(){;}
cogs1825

HEOI2016 排序

链接:http://cogs.pro/cogs/problem/problem.php?pid=2276

题意:区间修改,每一次对于一个子区间进行升序排列、降序排列,问最后某个位置的值是多少。

我们可以发现:当我们钦定一个答案的时候,可以得出最后结果是大于还是小于这个钦定结果的。很明显这个东西具有单调性。那么我们就二分答案,对于每个答案线段树验证即可。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lson root<<1,l,mid
  6 #define rson root<<1|1,mid+1,r
  7 #define lc root<<1
  8 #define rc root<<1|1
  9 using namespace std;
 10 const int maxn=100005;
 11 int sm[maxn<<2],st[maxn<<2],a[maxn];
 12 void Build(int root,int l,int r,int val)
 13 {
 14     st[root]=-1;
 15     if(l==r)
 16     {
 17         if(a[l]>=val)sm[root]=1;
 18         else sm[root]=0;
 19         return;
 20     }
 21     int mid=(l+r)>>1;
 22     Build(lson,val);Build(rson,val);
 23     sm[root]=sm[lc]+sm[rc];
 24 }
 25 void pushdown(int root,int l,int r)
 26 {
 27     if(l==r)return;
 28     if(st[root]!=-1)
 29     {
 30         st[lc]=st[rc]=st[root];
 31         int mid=(l+r)>>1;
 32         sm[lc]=st[lc]*(mid-l+1);
 33         sm[rc]=st[rc]*(r-mid);
 34         st[root]=-1;
 35     }
 36 }
 37 void pushup(int root)
 38 {
 39     sm[root]=sm[lc]+sm[rc];
 40 }
 41 int Query(int root,int l,int r,int L,int R)
 42 {
 43     if(L<=l&&r<=R)return sm[root];
 44     pushdown(root,l,r);
 45     int mid=(l+r)>>1,ans=0;
 46     if(R<=mid)ans=Query(lson,L,R);
 47     else if(L>mid)ans=Query(rson,L,R);
 48     else
 49     {
 50         ans+=Query(lson,L,mid);
 51         ans+=Query(rson,mid+1,R);
 52     }
 53     return ans;
 54 }
 55 void Set(int root,int l,int r,int L,int R,int val)
 56 {
 57     if(L>R)return;
 58     if(L<=l&&r<=R)
 59     {
 60         st[root]=val;
 61         sm[root]=val*(r-l+1);
 62         return;
 63     }
 64     int mid=(l+r)>>1;
 65     pushdown(root,l,r);
 66     if(R<=mid)Set(lson,L,R,val);
 67     else if(L>mid)Set(rson,L,R,val);
 68     else
 69     {
 70         Set(lson,L,mid,val);
 71         Set(rson,mid+1,R,val);
 72     }
 73     pushup(root);
 74 }
 75 int n,m,q;
 76 struct Ques
 77 {
 78     int l,r,val;
 79 }qu[maxn];
 80 bool Check(int val)
 81 {
 82     Build(1,1,n,val);
 83     for(int i=1;i<=m;i++)
 84     {
 85         int wal=Query(1,1,n,qu[i].l,qu[i].r);
 86         int fenjiexian;
 87         if(qu[i].val)
 88         {
 89             fenjiexian=qu[i].l+wal-1;
 90             Set(1,1,n,qu[i].l,fenjiexian,1);
 91             Set(1,1,n,fenjiexian+1,qu[i].r,0);
 92         }
 93         else
 94         {
 95             fenjiexian=qu[i].r-wal+1;
 96             Set(1,1,n,qu[i].l,fenjiexian-1,0);
 97             Set(1,1,n,fenjiexian,qu[i].r,1);
 98         }
 99     }
100     int k=Query(1,1,n,q,q);
101     if(k)return 1;
102     else return 0;
103 }
104 int haha()
105 {
106     freopen("heoi2016_sort.in","r",stdin);
107     freopen("heoi2016_sort.out","w",stdout);
108     scanf("%d%d",&n,&m);
109     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
110     for(int i=1;i<=m;i++)scanf("%d%d%d",&qu[i].val,&qu[i].l,&qu[i].r);
111     scanf("%d",&q);
112     int l=1,r=n,ans;
113     while(l<=r)
114     {
115         int mid=(l+r)>>1;
116         if(Check(mid))
117             l=mid+1;
118         else r=mid-1;
119     }
120     printf("%d
",r);
121 }
122 int sb=haha();
123 int main(){;}
cogs2276

Tower

挖坑……

(所以这么多坑我填的完么……)

只要是活着的东西,就算是神我也杀给你看。
原文地址:https://www.cnblogs.com/Loser-of-Life/p/7239018.html