2017.11.04离线赛总结
来源:互联网 发布:买了域名怎么卖 编辑:程序博客网 时间:2024/06/05 17:20
foreat ——3805
思路:显然的二分答案,不解释。
robot ——3806
思路:有点不明显的状压dp(但看数据范围还是能猜出来的),状压颜色,然而还要前缀和预处理一下,并且每次找该状态的lowbit转移。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#include<vector>using namespace std;#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define db double#define inf 0x7fffffff#define INF 0x3f3f3f3f#define mcl(a,b) memset(a,b,sizeof(a))#define Sz(a) sizeof(a)#define N 100005#define M 20int n,K;int A[N];struct p20{ vector<int>E[N]; LL calc(int col){ LL ans=0; int m=E[col].size(); if(m==1)return 0; int x=m; for(int i=0;i<m;i++){ int p=E[col][i]; int s=n-x+1; ans+=s-p; x--; } return ans; } void solve(){ for(int i=1;i<=n;i++)scanf("%d",&A[i]),E[A[i]].push_back(i); printf("%lld\n",min(calc(1),calc(2))); }}p20;struct p100{ int cnt[M]; LL sum[1<<M][M],last[M][M]; LL dp[1<<M]; int base[1<<M]; void Init(){ mcl(dp,INF); REP(i,0,K-1)base[1<<i]=i,sum[0][i]=dp[1<<i]=0; } void solve(){ REP(i,0,n-1){ scanf("%d",&A[i]); A[i]--; } Init(); DREP(i,n-1,0){ REP(j,0,K-1)if(j!=A[i])last[A[i]][j]+=cnt[j]; cnt[A[i]]++; } REP(i,1,(1<<K)-1){ REP(j,0,K-1){ if((i&(1<<j)))continue; int x=i&(-i); sum[i][j]=sum[i-x][j]+last[j][base[x]]; } } REP(i,0,(1<<K)-1){ REP(j,0,K-1){ if(i&(1<<j))continue; dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+sum[i][j]); } } cout<<dp[(1<<K)-1]<<endl; }}p100;int main(){// freopen("robot.in","r",stdin);// freopen("robot.out","w",stdout); cin>>n>>K; if(K==2)p20.solve(); else p100.solve(); return 0;}
tree ——3807
思路:与Paths神似,两条路径是否相交,即判断一条的lca是否被另一条路径经过,那么玄学的按照lca的deep从小到大排序,最后线段树维护一下即可求出答案。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#include<vector>using namespace std;#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define db double#define inf 0x7fffffff#define INF 0x3f3f3f3f#define mcl(a,b) memset(a,b,sizeof(a))#define Sz(a) sizeof(a)#define lson L,mid,p<<1#define rson mid+1,R,p<<1|1#define root 1,n,1 #define N 100005#define M 1005int n,m;LL ans;vector<int>E[N],vis[N];int D[N],fa[N],son[N],top[N],sz[N];int sgID[N],List[N],T;int mark[M][M];struct Node{ int from,to,lca; bool operator<(const Node &a)const{ return D[lca]<D[a.lca]; }}Q[N];void dfs1(int x,int f){ D[x]=D[f]+1; son[x]=0; sz[x]=1; fa[x]=f; REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==f)continue; dfs1(y,x); sz[x]+=sz[y]; if(sz[y]>sz[son[x]])son[x]=y; } }void dfs2(int x,int tp){ top[x]=tp; sgID[x]=++T; List[T]=x; if(son[x])dfs2(son[x],tp); REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==fa[x] || y==son[x])continue; dfs2(y,y); } }int Lca(int a,int b){ while(top[a]!=top[b]){ if(D[top[a]]<D[top[b]])swap(a,b); a=fa[top[a]]; } return D[a]<D[b]?a:b;}struct p60{ void solve(){ dfs1(1,0); dfs2(1,1); REP(i,1,m){ int a=Q[i].from,b=Q[i].to,lca=Lca(a,b); vis[lca].push_back(i); while(a!=lca){ vis[a].push_back(i); a=fa[a]; } while(b!=lca){ vis[b].push_back(i); b=fa[b]; } } LL ans=0; REP(i,1,n){ if(vis[i].size()<2)continue; REP(j,0,vis[i].size()-1){ REP(k,j+1,vis[i].size()-1){ int x=vis[i][j],y=vis[i][k]; if(x==y ||mark[x][y])continue; mark[x][y]=mark[y][x]=1; ans++; } } } cout<<ans<<endl; }}p60;struct p100{ struct Tree{ struct node{ int L,R,sum; }tree[N<<2]; void build(int L,int R,int p){ tree[p].L=L,tree[p].R=R; tree[p].sum=0; if(L==R)return; int mid=(L+R)>>1; build(lson),build(rson); } void update(int L,int R,int p){ if(tree[p].L==L && tree[p].R==R){ tree[p].sum++; return; } int mid=(tree[p].L+tree[p].R)>>1; if(R<=mid)update(L,R,p<<1); else if(L>mid)update(L,R,p<<1|1); else update(lson),update(rson); } void query(int x,int p){ ans+=tree[p].sum; if(tree[p].L==tree[p].R)return; int mid=(tree[p].L+tree[p].R)>>1; if(x<=mid)query(x,p<<1); else query(x,p<<1|1); } }Tree; void change(int a,int b){ while(top[a]!=top[b]){ if(D[top[a]]<D[top[b]])swap(a,b); Tree.update(sgID[top[a]],sgID[a],1); a=fa[top[a]]; } if(D[a]>D[b])swap(a,b); Tree.update(sgID[a],sgID[b],1); } void solve(){ dfs1(1,0); dfs2(1,1); REP(i,1,m)Q[i].lca=Lca(Q[i].from,Q[i].to); sort(Q+1,Q+1+m); Tree.build(root); REP(i,1,m){ Tree.query(sgID[Q[i].lca],1); change(Q[i].from,Q[i].to); } cout<<ans<<endl; }}p100;int A[N<<1]; LL cnt[N],sum[N];struct p_list{ bool check(){ REP(i,1,n)if(E[i].size()>2)return 0; return 1; } void dfs(int x,int f){ D[x]=D[f]+1; REP(i,0,E[x].size()-1){ int y=E[x][i]; if(y==f)continue; dfs(y,x); } } void solve(){ int mm=0,s; REP(i,1,n)if(E[i].size()==1){s=i;break;} dfs(s,0); REP(i,1,m){ int a=D[Q[i].from],b=D[Q[i].to]; if(a>b)swap(a,b); A[++mm]=a; A[++mm]=b+1; cnt[a]++; sum[b+1]++; } sort(A+1,A+mm+1); int len=unique(A+1,A+mm+1)-A-1; int now=0; LL ans=0; REP(i,1,len){ now-=sum[A[i]]; if(cnt[A[i]]>0)ans+=1LL*now*cnt[A[i]]+1LL*cnt[A[i]]*(cnt[A[i]]-1)/2; now+=cnt[A[i]]; } cout<<ans<<endl; }}p_list;int main(){// freopen("tree.in","r",stdin);// freopen("tree.out","w",stdout); cin>>n>>m; REP(i,1,n-1){ int a,b; scanf("%d%d",&a,&b); E[a].push_back(b); E[b].push_back(a); } REP(i,1,m)scanf("%d%d",&Q[i].from,&Q[i].to); if(n<=1000)p60.solve(); else if(p_list.check())p_list.solve(); else p100.solve(); return 0;}
小结:今天考得不错,but第1题并不是敲了一遍就对了,还对拍了很久的小数据(该证明的还是要证明,该贪心的还是要贪心),并且要多考虑数据的一些下界和上界(很容易边界炸!!!);对dp还要再敏感一些,树上的题目该水的分一定要先水,再看有没有链的(话说这几次链的数据几乎都是错的…链还是多想想,这档分与正解相比不会太难)。
阅读全文
0 0
- 2017.11.04离线赛总结
- 2017.11.03离线赛总结
- 2017.11.05离线赛总结
- 2017.11.06离线赛总结
- 2017.11.07离线赛总结
- 2017.11.08离线赛总结
- 2017.11.09离线赛总结
- 离线赛20171004总结
- 离线赛20171006总结
- 20171006离线赛总结
- 20171007离线赛总结
- 离线赛20171007总结
- 离线赛20171008总结
- 离线赛20171008总结
- 离线赛总结
- 20171009离线赛总结
- 10.10离线赛总结
- 离线赛20171010总结
- Spring Aop(十三)——ProxyFactoryBean创建代理对象
- 与老同学聊天
- hdu 1007 Quoit Design(套圈游戏)
- 51nod 1240 莫比乌斯函数
- Fast_RCNN论文笔记
- 2017.11.04离线赛总结
- Linux技巧
- 《Android开发艺术探索》笔记(View的知识体系)
- 点击按钮,ajax提交报错
- [Python] openpyxl读存大数据 Exception: String longer than 32767 characters
- Java入门和进阶必读书单
- linux中的存储设备的管理
- 极限学习机应用于入侵检测(一)
- docker compose 应用案例 web负载均衡