1001 - 深海里的大菠萝

显然这么小的数据范围我们瞎暴力就行了。然后就能得出来凸包上合法的点对。然后我贪心wa了,发现了反例,感觉是dp,不会dp,卒

其实dp很简单,我们在普通的区间dp上枚举断点更新完答案之后再看区间首尾合不合法即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef double db;
 4 const db eps=1e-10;
 5 int sign(db k){
 6     if (k>eps) return 1; else if (k<-eps) return -1; return 0;
 7 }
 8 int cmp(db k1,db k2){return sign(k1-k2);}
 9 int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}
10 struct point{
11     db x,y;
12     point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
13     point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
14     point operator * (db k1) const{return (point){x*k1,y*k1};}
15     point operator / (db k1) const{return (point){x/k1,y/k1};}
16     int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
17     bool operator < (const point k1) const{
18         int a=cmp(x,k1.x);
19         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
20     }
21     db abs(){return sqrt(x*x+y*y);}
22     db abs2(){return x*x+y*y;}
23     db dis(point k1){return ((*this)-k1).abs();}
24 };
25 int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
26 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
27 db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
28 point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
29     point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
30 }
31 db disSP(point k1,point k2,point q){
32     point k3=proj(k1,k2,q);
33     if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
34 }
35 vector<point> ConvexHull(vector<point>A,int flag=0){ // flag=0 不严格 flag=1 严格
36     int n=A.size(); vector<point>ans(n*2);
37     sort(A.begin(),A.end()); int now=-1;
38     for (int i=0;i<A.size();i++){
39         while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
40         ans[++now]=A[i];
41     } int pre=now;
42     for (int i=n-2;i>=0;i--){
43         while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
44         ans[++now]=A[i];
45     } ans.resize(now); return ans;
46 }
47 int T,n,g;point o[105];db R;
48 int dp[404][404],b[404][404];
49 vector<point> v;point p;
50 bool can(point a,point b) {
51     for (int i = 0; i < g; i++){
52         if(cmp(disSP(a,b,o[i]),R)<=0)
53             return false;
54     }
55     return true;
56 }
57 int main(){
58     scanf("%d",&T);
59     while (T--){
60         v.clear();
61         memset(b,0, sizeof(b));
62         memset(dp,0, sizeof(dp));
63         scanf("%d%d%lf",&n,&g,&R);
64         for(int i=1;i<=n;i++){
65             scanf("%lf%lf",&p.x,&p.y);
66             v.push_back(p);
67         }
68         for(int i=0;i<g;i++){
69             scanf("%lf%lf",&o[i].x,&o[i].y);
70         }
71         v=ConvexHull(v);
72         int m = v.size();
73         for(int i=0;i<m-1;i++){
74             for(int j=i+2;j<m;j++){
75                 if(i==0&&j==m-1)continue;
76                 if(can(v[i],v[j])) {
77                     b[i][j]=b[j][i]=1;
78                 }
79             }
80         }
81         for(int len=3;len<=m;len++){
82             for(int i=0;i+len-1<m;i++){
83                 int ed = i+len-1;
84                 for(int j=i;j<=ed;j++){
85                     dp[i][ed]=max(dp[i][ed],dp[i][j]+dp[j][ed]);
86                 }
87                 dp[i][ed]+=b[i][ed];
88             }
89         }
90         printf("%d\n",dp[0][m-1]);
91     }
92 }

View Code

1002 - Yukikaze and Demons

dag上的支配集,增加汇点将所有出度为零的点汇聚,反向建图拓扑排序,如果点x要被ban掉,不能到达汇点,则需要x的所有父亲的lca被ban掉,所以求出其lca,将其挂在lca下面即可。如此建树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=1e5+5;
int T, n, m, indeg[maxn], par[maxn][20], depth[maxn];
vector<int>g[maxn], p[maxn];
queue<int>q;
void init(){memset(par,-1,sizeof(par));for(int i=1;i<=n+1;i++) g[i].clear(),p[i].clear(), indeg[i]=0;
}
int lca(int u, int v){if(depth[u]<depth[v]) swap(u,v);int t=depth[u]-depth[v];for(int i=0;i<=18;i++){if(t&(1<<i)) u=par[u][i];}if(u==v) return u;for(int i=18;i>=0;i--){if(par[u][i]!=par[v][i]) u=par[u][i], v=par[v][i];}return par[u][0];
}
void update(int u, int fa){par[u][0]=fa; depth[u]=depth[fa]+1;for(int i=1;i<=18;i++){if(par[u][i-1]==-1) par[u][i]=-1;else par[u][i]=par[par[u][i-1]][i-1];}
}
void topsort(){q.push(n);while(!q.empty()){int u=q.front(); q.pop();if(u!=n){int fa=p[u][0];for(int i=1;i<p[u].size();i++){fa=lca(fa,p[u][i]);}update(u,fa);}for(int i=0;i<g[u].size();i++){int v=g[u][i]; indeg[v]--;if(!indeg[v]) q.push(v);}}
}
int main(){scanf("%d",&T);while(T--){scanf("%d%d",&n,&m); init(); int u, v;for(int i=1;i<=m;i++) scanf("%d%d",&u,&v), g[v].push_back(u), indeg[u]++, p[u].push_back(v);for(int i=1;i<=n;i++) if(!indeg[i]) g[n+1].push_back(i), p[i].push_back(n+1), indeg[i]++;n++; depth[n]=0;topsort();int q; scanf("%d",&q);while(q--){scanf("%d%d",&u,&v);printf("%d\n",depth[u]+depth[v]-depth[lca(u,v)]);}}return 0;
}

View Code

1011 - Squrirrel

$dp$。如果不删边,那么这个题就是个很经典的原题,现在删边的话,其实就是在不删边的基础上进行一定的修改和维护。我们用$down[u][0]$和$down[u][1]$表示节点$u$向子树走的不删边的最长路和删边的最长路,用$up[u][0]$和$up[u][1]$表示向父亲走的对应的最长路。对于$down[u][0]$,转移很显然,现在考虑$down[u][1]$,如果要删除边,我们一定会选择$down[u][0]$对应的那棵子树的一条边,因为这样才能缩短最长路,但是我们不能就把缩短后的最长路当做是$down[u][1]$,因为也许去往其他子树的不删边的最长路比它更长,所以,我们在求$down[u][0]$时,不仅要求最长路,还要求一个次长路,且这两条路去往不同的子树,最后$down[u][1]$就是在次长路和最长路对应的那棵子树删边后的最长路之间取最大值。$up[u][0]$和$up[u][1]$的求法稍稍复杂点,设$f$是$u$的父亲,对于$up[u][0]$,它分两种情况,一种是它先到$f$,再往$f$的祖先方向走,另一种是它先到$f$,再往$f$的另一颗子树走,前一种情况转移显然,后一种的话,前面维护的最长路和次长路再次起作用,这里不赘述。而$up[u][1]$,将会更复杂些,为了更容易的分析,我们不妨以$f$为根,并且删除$u$这棵子树,这样的话,其实就等价于在新的树中对$f$求$down[f][0]$和$down[f][1]$,最后加上$f$到$u$的边权即可(也可能选择删这条边,但不影响)。前面说了这样需要维护最大值和次大值,然后就很容易求了,但是呢,我们不能真的删除$u$对应的子树,所以$u$这棵子树的影响我们需要想办法排除,因此,我们不妨维护前三大值,如果$u$这棵子树对应的值在前三大值中,直接删去,就可以得到实际用到的最大值的次大值,其他的就和前面一样了,具体细节看代码。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 const int N=2e5+5;
 6 int down[N][2][2];
 7 int up[N][2];
 8 int T,n;
 9 typedef std::pair<int,int> P;
10 std::vector<P> g[N];
11 void init() {
12     for(int i=1;i<=n;i++) g[i].clear();
13 }
14 void dfs(int u,int fa) {
15     memset(down[u],0,sizeof(down[u]));
16     for(P c:g[u]) if(c.first!=fa){
17         int v=c.first;
18         dfs(v,u);
19         int L=down[v][0][0]+c.second;
20         if(L>down[u][0][0]) {
21             down[u][0][1]=down[u][0][0];
22             down[u][0][0]=L;
23         }
24         else if(L>down[u][0][1]) {
25             down[u][0][1]=L;
26         }
27     }
28     for(P c:g[u]) if(c.first!=fa) {
29         int v=c.first;
30         int L=down[v][0][0]+c.second,R=std::min(down[v][1][0]+c.second,down[v][0][0]);
31         if(L==down[u][0][0]) {
32             down[u][1][0]=std::max(R,down[u][0][1]);
33             break;
34         }
35     }
36     //printf("%d %d %d %d\n",u,down[u][0][0],down[u][0][1],down[u][1][0]);
37 }
38 void dfs2(int u,int fa) {
39     P s[3];
40     s[0]=P(up[u][0],up[u][1]);
41     s[1]=s[2]=P(0,0);
42     for(P c:g[u]) if(c.first!=fa) {
43         int v=c.first;
44         P t(down[v][0][0]+c.second,std::min(down[v][1][0]+c.second,down[v][0][0]));
45         if(t>s[0]) {
46             s[2]=s[1];
47             s[1]=s[0];
48             s[0]=t;
49         }
50         else if(t>s[1]) {
51             s[2]=s[1];
52             s[1]=t;
53         }
54         else if(t>s[2]) s[2]=t;
55     }
56     for(P c:g[u]) if(c.first!=fa) {
57         int v=c.first;
58         up[v][0]=up[u][0]+c.second;
59         int L=down[v][0][0]+c.second;
60         if(down[u][0][0]==L) up[v][0]=std::max(up[v][0],c.second+down[u][0][1]);
61         else up[v][0]=std::max(up[v][0],c.second+down[u][0][0]);
62         P t(down[v][0][0]+c.second,std::min(down[v][1][0]+c.second,down[v][0][0]));
63         int p=-1;
64         static int l,r;
65         for(int i=0;i<3;i++) if(t==s[i]) p=i;
66         up[v][1]=p?s[0].first:s[1].first;
67         l=p?0:1;
68         for(int i=0;i<3;i++) {
69             if(i==l||i==p) continue;
70             r=i;break;
71         }
72         up[v][1]=std::min(up[v][1],std::max(s[l].second,s[r].first)+c.second);
73         dfs2(v,u);
74     }
75     //printf("--%d %d %d\n",u,up[u][0],up[u][1]);
76 }
77 int main() {
78     scanf("%d",&T);
79     while(T--) {
80         scanf("%d",&n);
81         init();
82         for(int i=1,u,v,w;i<n;i++) {
83             scanf("%d%d%d",&u,&v,&w);
84             g[u].push_back(P(v,w));
85             g[v].push_back(P(u,w));
86         }
87         dfs(1,0);up[1][0]=up[1][1]=0;
88         dfs2(1,0);
89         int ans=1,val=std::min(std::max(down[1][0][0],up[1][1]),std::max(down[1][1][0],up[1][0]));
90         for(int i=2;i<=n;i++) {
91             int tmp=std::min(std::max(down[i][0][0],up[i][1]),std::max(down[i][1][0],up[i][0]));
92             if(tmp<val) ans=i,val=tmp;
93         }
94         printf("%d %d\n",ans,val);
95     }
96     return 0;
97 }

View Code

容易想歪,容易写歪 &我的代码果然比楼上短

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
const int maxn=2e5+5;
const int inf=1e9+7;
int up[maxn][2], down[maxn], c[maxn];
int t[maxn][3], p[maxn][3];
int T, n, m;
vector<P>g[maxn];
void init(){for(int i=1;i<=n;i++){up[i][0]=up[i][1]=0; down[i]=0; g[i].clear(); c[i]=0;for(int j=0;j<3;j++) t[i][j]=0, p[i][j]=-1;}
}
void solve(int u, int fa){int mx1=-1, mx2=-1, mx3=-1;for(int i=0;i<g[u].size();i++){P pr=g[u][i]; int v=pr.first;if(v==fa) continue;solve(v,u); int a=t[v][0]; c[v]=pr.second;if(mx1==-1||t[mx1][0]+c[mx1]<a+c[v]) mx3=mx2, mx2=mx1, mx1=v;else if(mx2==-1||t[mx2][0]+c[mx2]<a+c[v]) mx3=mx2, mx2=v;else if(mx3==-1||t[mx3][0]+c[mx3]<a+c[v]) mx3=v;}if(mx1!=-1) t[u][0]=t[mx1][0]+c[mx1]; p[u][0]=mx1;if(mx2!=-1) t[u][1]=t[mx2][0]+c[mx2]; p[u][1]=mx2;if(mx3!=-1) t[u][2]=t[mx3][0]+c[mx3]; p[u][2]=mx3;if(p[u][0]!=-1){int v=p[u][0];down[u]=max(min(down[v]+c[v],t[v][0]),t[u][1]);}
}
void dfs2(int u, int fa){for(int i=0;i<g[u].size();i++){P pr=g[u][i]; int v=pr.first;if(v==fa) continue; int mx=0;int x=0;if(p[u][0]==v){mx=t[u][1]; if(p[u][1]!=-1) {int y=min(down[p[u][1]]+c[p[u][1]],t[p[u][1]][0]);x=max(y,t[u][2]);}}else{mx=t[u][0];int w=0;if(p[u][1]==v) w=t[u][2];else w=t[u][1];if(p[u][0]!=-1){int y=min(down[p[u][0]]+c[p[u][0]], t[p[u][0]][0]); x=max(y,w);}}up[v][0]=max(up[u][0]+pr.second,mx+pr.second);int a=max(up[u][1],mx)+pr.second; int c=max(up[u][0],mx);int b=max(up[u][0],x)+pr.second; up[v][1]=min(a,min(b,c));dfs2(v,u);}
}
int main(){scanf("%d",&T);while(T--){scanf("%d",&n); int u, v, w;init();for(int i=1;i<=n-1;i++) scanf("%d%d%d",&u,&v,&w), g[u].push_back(P(v,w)), g[v].push_back(P(u,w));solve(1,-1); dfs2(1,-1);int ans=inf; int pos=-1;for(int i=1;i<=n;i++){int x=ans;ans=min(ans,max(down[i],up[i][0]));ans=min(ans,max(t[i][0],up[i][1]));ans=min(ans,max(t[i][0],up[i][0]));if(ans!=x)  pos=i;}printf("%d %d\n",pos,ans);}return 0;
}

View Code

转载于:https://www.cnblogs.com/Onlymyheart/p/11267401.html

2019 Multi-University Training Contest 3 题解相关推荐

  1. 2016 Multi-University Training Contest 10

    solved 7/11 2016 Multi-University Training Contest 10 题解链接 分类讨论 1001 Median(BH) 题意: 有长度为n排好序的序列,给两段子 ...

  2. 2019 Multi-University Training Contest 7 部分补题

    2019 Multi-University Training Contest 7 部分补题 这场比赛三个人一起组队,比赛期间自己感觉并没有奉献多少东西,所以补题.而且总感觉比赛到后期很乏力(没力气那种 ...

  3. HDU 2019 Multi-University Training Contest 1 杭电2019多校联合训练赛 第一场 1001 Blank (6578)

    HDU 2019 Multi-University Training Contest 1 杭电2019暑期多校集训第一场 1001 Blank (6578) Problem Description T ...

  4. HDU 6638 [2019 Multi-University Training Contest 6]

    Snowy Smile Problem Description There are n pirate chests buried in Byteland, labeled by 1,2,-,n. Th ...

  5. 2022/7/4/题解[CCSU Summer Training Contest 1 - Virtual Judge (vjudge.net)](https://vjudge.net/contest/

    2022/7/4/题解CCSU Summer Training Contest 1 - Virtual Judge (vjudge.net) A题:Problem - 1594A - Codeforc ...

  6. 2017 Multi-University Training Contest - Team 1

    2017 Multi-University Training Contest - Team 1 01     签到的 #include<bits/stdc++.h> using names ...

  7. 2017 Multi-University Training Contest - Team 7:1003. Color the chessboard(...)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  8. 2017 Multi-University Training Contest - Team 7:1002. Build a tree(递归)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  9. 2017 Multi-University Training Contest - Team 7:1010. Just do it(组合数?)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  10. 2017 Multi-University Training Contest - Team 7:1008. Hard challenge(模拟)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

最新文章

  1. 实战Linux Bluetooth编程(四) L2CAP层编程
  2. VR中的白帽机制,这把安全的双刃剑应该如何使用?
  3. 基于SSH实现在线课程学习系统
  4. Faster-RCNN 自己的数据训练
  5. 【转】Java里如何实现线程间通信
  6. ajax 请求svg,jQuery append 到AJAX加载的SVG问题
  7. 为什么大厂们 一边裁员,一边招人。。
  8. 外媒确认iPhone 13 Pro系列采用120Hz OLED面板:支持智能调节屏幕刷新率
  9. java log输出到文件路径_log4j中日志输出文件指定相对路径的方法
  10. php读取西门子plc_第三方设备如何读取PLC数据
  11. 对txt文件的高频词汇统计
  12. Navicat还原nb3备份文件
  13. 阿里云RDS数据库与自建数据库做主从同步
  14. 2020iPS细胞研究进展综述
  15. 期货开户手续费是怎么查询?
  16. 基于Rsyslog的日志文件采集办法
  17. [hackthebox]shibboleth
  18. 宝宝头上有一圈不长头发
  19. 前馈神经网络FNN(原理及实现)
  20. 【天光学术】民法学论文:从税收法定主义看我国税收立法之不足【开题报告 硕士研究生毕业论文】

热门文章

  1. ping一下网站服务器的域名,怎么PING一个网站的域名
  2. 绝对简单易学的PHP入门教程
  3. 笔记本禁用键盘和触摸板
  4. centos7安装Memcached
  5. C语言:二维数组传参的格式(详细+总结)
  6. 求助各位大神JSP报错急急急!!!!感激不尽
  7. linux kvm usb设备,KVM使用USB设备的方法
  8. 五脏与五声 五脏排毒法(五声功)
  9. vue实现文件下载功能
  10. 面试系列--如何自我介绍