BestCoder Round #74 (div.2)
来源:互联网 发布:淘宝上卖自己做的熟食 编辑:程序博客网 时间:2024/06/04 18:05
未完待续~~
划分等价类,判断是否无解,26*25^(m-1)即可,倒着来~
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010#define Mod 1000000007LLint n;int A[N];long long Dp[N];inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}int main(){ int T=read(); while(T--) { n=read(); memset(Dp,0,sizeof(Dp)); memset(A,0,sizeof(A)); Dp[n]=26; for(int i=1;i<=n-1;i++) A[i]=read(); for(int i=n-1;i>=1;i--) { if(A[i]==0) Dp[i]=Dp[i+1]*25%Mod; else if(A[i]==A[i+1]+1) Dp[i]=Dp[i+1]; else { Dp[i]=0; break; } } printf("%I64d\n",Dp[1]); } return 0;}
直接对新的点建图,然后flyod,最后算答案的是后6*6,枚举转折点更新答案即可!
#include<bits/stdc++.h>using namespace std;#define ll long longconst int maxn=1e5+10;int a[10],dis[10][10],n,m;const ll mod=1e9+7;int main(){ int t;cin>>t; while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=6;i++){ scanf("%d",&a[i]); } for(int i=1;i<=6;i++){ for(int j=1;j<=6;j++){ dis[i][j]=abs(a[i]-a[j]); } } for(int i=1;i<=5;i+=2){ dis[i][i+1]=dis[i+1][i]=1; } for(int k=1;k<=6;k++){ for(int i=1;i<=6;i++){ for(int j=1;j<=6;j++){ dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } } } int s,t;ll anss=0; for(ll k=1;k<=m;k++){ scanf("%d%d",&s,&t); ll ans=abs(s-t); for(int i=1;i<=6;i++){ for(int j=1;j<=6;j++){ ans=min(ans,(ll)(abs(s-a[i])+abs(t-a[j])+dis[i][j])); } } anss=(anss+k*ans)%mod; } printf("%lld\n",anss); }}
利用异或性质进行bfs,O(1)查询!
#include<bits/stdc++.h>using namespace std;#define ll long longconst ll mod=1e9+7;const int maxn=1e6+10;int dis[maxn],vis[maxn];int n,m,a[20],s,t;void bfs(){ queue<int>q; while(!q.empty())q.pop(); q.push(0);dis[0]=0;vis[0]=1; while(!q.empty()){ int now=q.front();q.pop(); for(int i=0;i<17;i++){ if(vis[(1<<i)^now]) continue; dis[(1<<i)^now]=dis[now]+1;q.push((1<<i)^now); vis[(1<<i)^now]=1; } for(int i=1;i<=n;i++){ if(vis[a[i]^now]) continue; dis[a[i]^now]=dis[now]+1;q.push(a[i]^now); vis[a[i]^now]=1; } }}int main(){ //cout<<"== "<<(1<<15)<<endl; int tt;cin>>tt; while(tt--){ ll anss=0; scanf("%d%d",&n,&m);memset(dis,0x7f7f7f7f,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){scanf("%d",&a[i]);} bfs(); for(ll i=1;i<=m;i++){ scanf("%d%d",&s,&t); anss=(anss+i*dis[s^t])%mod; } printf("%lld\n",anss); }}
题意:求删除恰好k条边后,能够使得字典序最小的拓扑序列~
题解:参考下普通的用堆维护求字典序最小拓扑序, 用某种数据结构维护入度小于等于kk的所有点, 每次找出编号最小的, 并相应的减少k即可.
这个数据结构可以用线段树, 建立一个线段树每个节点[l,r][l,r]维护编号从ll到rr的所有节点的最小入度, 查询的时候只需要在线段树上二分, 找到最小的xx满足入度小于等于k.
这个结构也可用优先队列,每次把入度小于等于k的入队,弹出序号最小的标号,把它作为拓扑的下一个,代价就是把它的入度全部用k删掉,然后把这个点以及它连的边都删掉,再更新入队的元素就可以了~
#include<bits/stdc++.h>#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))#if defined(_MSC_VER) || __cplusplus > 199711L#define aut(r,v) auto r = (v)#else#define aut(r,v) __typeof(v) r = (v)#endif#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)#define all(o) (o).begin(), (o).end()#define pb(x) push_back(x)#define mp(x,y) make_pair((x),(y))#define mset(m,v) memset(m,v,sizeof(m))#define INF 0x3f3f3f3f#define INFL 0x3f3f3f3f3f3f3f3fLLusing namespace std;typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll;template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }int main() { int T; scanf("%d", &T); for(int ii = 0; ii < T; ++ ii) { int n; int m; int k; scanf("%d%d%d", &n, &m, &k); vector<vector<int> > g(n); vi deg(n); for(int i = 0; i < m; ++ i) { int u, v; scanf("%d%d", &u, &v), -- u, -- v; g[u].push_back(v); ++ deg[v]; } priority_queue<int,vi,greater<int> > q; rep(i, n) if(deg[i] <= k) q.push(i); vector<bool> used(n, false); ll anssum = 0; rep(t, n) { int i; while(1) { i = q.top(); q.pop(); if(!used[i] && deg[i] <= k) break; } // cout<<"i= "<<i<<endl; anssum += (ll)(t + 1) * (i + 1); k -= deg[i]; used[i] = true; each(j, g[i]) if(!used[*j]) { if(-- deg[*j] <= k) q.push(*j); } } printf("%d\n", (int)(anssum % 1000000007)); } return 0;}
线段树不过就是换一种数据结构来维护罢了,方法都是一样的~
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int N=100010;const int mo=1e9+7;struct bian{ int next,point;}b[410000];int num[N<<2],d[N],n,m,p[N],K,len,where,w;void add(int k1,int k2){ d[k2]++; b[++len]=(bian){p[k1],k2}; p[k1]=len;}void buildtree(int k1,int k2,int k3){ if (k2==k3){ num[k1]=d[k2]; return; } int mid=k2+k3>>1; buildtree(k1*2,k2,mid); buildtree(k1*2+1,mid+1,k3); num[k1]=min(num[k1*2],num[k1*2+1]);}int find(int k1,int k2,int k3){// cout<<"fa "<<k1<<" "<<num[k1]<<" "<<num[k1*2]<<" "<<k2<<" "<<k3<<" "<<K<<endl; if (k2==k3) return k2; int mid=k2+k3>>1; if (num[k1*2]<=K) return find(k1*2,k2,mid); else return find(k1*2+1,mid+1,k3);}void change(int k1,int k2,int k3){ if (k2==k3){ num[k1]=d[where]; return; } int mid=k2+k3>>1; if (mid>=where) change(k1*2,k2,mid); else change(k1*2+1,mid+1,k3); num[k1]=min(num[k1*2],num[k1*2+1]);}void solve(){ scanf("%d%d%d",&n,&m,&K); len=0; for (int i=1;i<=n;i++) p[i]=0,d[i]=0; for (int i=1;i<=m;i++){ int k1,k2; scanf("%d%d",&k1,&k2); add(k1,k2); } buildtree(1,1,n); int ans=0; for (int t=1;t<=n;t++){ int now=find(1,1,n); ans=(ans+1ll*t*now)%mo; // cout<<"faaa "<<now<<" "<<d[now]<<" "<<K<<endl; K-=d[now]; for (int i=p[now];i;i=b[i].next){ int j=b[i].point; d[j]--; where=j; change(1,1,n); } where=now; d[now]=1e9; change(1,1,n); } printf("%d\n",ans);}int main(){ int t; scanf("%d",&t); for (;t;t--) solve(); return 0;}
0 0
- BestCoder Round #74 (div.2)
- hdu 5637 BestCoder Round #74 (div.2)
- hdu5635 BestCoder Round #74 (div.2)
- BestCoder Round #74 (div.2) LCP Array
- BestCoder Round #74 (div.2)【1排列组合】
- BestCoder Round #11 (Div. 2)
- BestCoder Round #11 (Div. 2)
- BestCoder Round #50 (div.2)
- BestCoder Round #50 (div.2)
- BestCoder Round 50 (div 2)
- BestCoder Round #50 (div.2)
- #BestCoder Round #50 (div.2)
- BestCoder Round #50 (div.2)
- BestCoder Round #54 (div.2)
- BestCoder Round #56 (div.2)
- BestCoder Round #58 (div.2)
- BestCoder Round #59 (div.2)
- BestCoder Round #59 (div.2)
- java/android基础总结1
- strcpy()
- 心理学学习(一) 心理学研究的基本方法
- Contains Duplicate II-副本包含
- PAT-Kuchiguse
- BestCoder Round #74 (div.2)
- 网络七层 以及iOS开发中的get请求 post请求
- retrofit--------样例代码
- 《机器学习实战》——回归
- 不同渲染路径下Pass执行规则总结
- 43. Multiply Strings
- Ant入门
- Mule ESB 入门,最简单的Hello实例
- 排序算法之导论