Codeforces Educational Codeforces Round 42 (Rated for Div. 2) D,E,F
2018-04-11 21:08
471 查看
D
题意
每次把最小的两个给合起来,然后把右边的一个变成这个数的两倍,问最后的序列分析
我的做法有点蠢,直接暴力合并,开一个权值线段树,叶子结点开个set存位置,然后维护同种元素最多出现多少个,一边找一边并就好最后把所有的叶子结点给扫一遍,map一下
代码
#include <bits/stdc++.h> #define ll long long using namespace std; const ll inf = 1e18; const ll N = 1234567; inline ll read() { ll p=0; ll f=1; char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();} return p*f; } ll rt,tot,lc[N<<2],rc[N<<2]; set<ll> s[N<<2]; ll c[N<<2]; void link(ll &u,ll L,ll R,ll k,ll cc) { if(!u) u=++tot; if(L==R) { s[u].insert(cc); c[u] = s[u].size(); return ; } ll mid = (L+R)>>1; if(k<=mid) link(lc[u],L,mid,k,cc); else link(rc[u],mid+1,R,k,cc); c[u] = max(c[lc[u]] , c[rc[u]]); } void find(ll u,ll L,ll R) { if(L==R) { s[u].erase(s[u].begin()); link(rt,1,inf,2*L,*s[u].begin()); s[u].erase(s[u].begin()); c[u] = s[u].size(); //printf("%d\n",L); return ; } ll mid=(L+R)>>1; if(c[lc[u]] >= 2) find(lc[u],L,mid); else find(rc[u],mid+1,R); c[u] = max(c[lc[u]] , c[rc[u]]); } map<ll,ll> mp; void qry(ll u,ll L,ll R) { if(!u) return ; if(L==R) { for(auto i : s[u]) mp[i]=L; return ; } ll mid=(L+R)>>1; qry(lc[u],L,mid); qry(rc[u],mid+1,R); } ll ans ; int main() { ll n = read(); rt=tot=0; for(ll i=1;i<=n;i++) { ll x=read(); link(rt,1,inf,x,i); } while(1) { if(c[1] <= 1) break; find(rt,1,inf); } qry(rt,1,inf); printf("%d\n",mp.size()); for(auto i:mp) printf("%lld ",i.second); return 0; }
E
题意
在坐标轴上有很多个点,R,B,P,然后你要把这些点给连边,代价为坐标的绝对值的差, 然后使得这个图去掉R点后B和P都仍然全部联通或者去掉B点后R和P仍然全部都联通分析
考虑P点之间的情况,要不就是P点之间连两条链,要不就是首先两个P点先连,然后对于R的点连向P点的情况就是分成两边,一边连前面的端点,一边连后面的端点,对于B也这样贪心,肯定有两个决策点,看看是连两条链优还是断开优代码
#include <bits/stdc++.h> #define ll long long using namespace std; const ll N = 1000010; inline ll read() { ll p=0; ll f=1; char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();} return p*f; } ll col ,a ; ll n; ll p ,plen = 0; int main() { n=read(); for(ll i=1;i<=n;i++) { ll x = read(); char ch; scanf("\n%c",&ch); if(ch=='R') col[i] = 1; else if(ch=='B') col[i] = 2; else col[i] = 3; a[i] = x; } ll s=0,d=n+1; for(ll i=1;i<=n;i++) if(col[i] == 3){s=i; break;} for(ll i=n;i>=1;i--) if(col[i] == 3){d=i; break;} if(s==0) { ll lst = 0; ll ans = 0; for(ll i=1;i<=n;i++) { if(col[i] == 2) continue; if(lst) ans+=a[i] - a[lst]; lst = i; } lst = 0; for(ll i=1;i<=n;i++) { if(col[i] == 1) continue; if(lst) ans+=a[i] - a[lst]; lst = i; }printf("%lld\n",ans); return 0; } ll lst = 0; ll ans = 0; for(ll i=1;i<=s;i++) { if(col[i] == 2) continue; if(lst) ans+=a[i] - a[lst]; lst = i; } lst = 0; for(ll i=1;i<=s;i++) { if(col[i] == 1) continue; if(lst) ans+=a[i] - a[lst]; lst = i; } lst = d; for(ll i=d+1;i<=n;i++) { if(col[i] == 2) continue; if(lst) ans+=a[i] - a[lst]; lst = i; } lst = d; for(ll i=d+1;i<=n;i++) { if(col[i] == 1) continue; if(lst) ans+=a[i] - a[lst]; lst = i; } ll nx = 0; for(ll i=s;i<d;i=nx) { ll ss = 0; nx = i+1; while(col[nx] !=3) nx++; plen = 0; for(ll j=i+1;j<nx;j++) { if(col[j] == 1) p[++plen] = j; } ll minx = LLONG_MAX; for(ll j=0;j<=plen;j++) { ll o = 0; if(j) o += a[p[j]] - a[i]; if(j+1<=plen) o += a[nx] - a[p[j+1]]; minx = min(minx , o); }ss+=minx; plen = 0; for(ll j=i+1;j<nx;j++) { if(col[j] == 2) p[++plen] = j; } minx = LLONG_MAX; for(ll j=0;j<=plen;j++) { ll o = 0; if(j) o += a[p[j]] - a[i]; if(j+1<=plen) o += a[nx] - a[p[j+1]]; minx = min(minx , o); }ss+=minx; ss += a[nx] - a[i]; ss = min(ss , 2 * (a[nx] - a[i])); // printf("%lld\n",ss); ans += ss; } return printf("%lld\n",ans),0; }
F
题意
问哪些边在简单环上分析
简单环就是一个点联通分量,点数和边数相同,一条边找到dfs序比较大的点,也就是深度比较大的点,这条边属于的联通分量就是这条边属于的联通分量(因为可能一个点属于多个联通分量)
代码
#include <bits/stdc++.h> #define pb push_back using namespace std; const int N = 1234567; inline int read() { int p=0; int f=1; char ch=g ca06 etchar(); while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();} return p*f; } struct node{int x,y,next;}edge ; int len,first ; void ins(int x,int y){len++; edge[len].x=x; edge[len].y=y; edge[len].next=first[x]; first[x]=len;} int dfn ,low ,id=0,cnt=0; stack<int> s; int n,m; vector<int> scc ; int bel ; void dfs(int x) { dfn[x] = low[x] = ++id; s.push(x); for(int k=first[x];k!=-1;k=edge[k].next) { int y = edge[k].y; if(dfn[y]==-1) { dfs(y); low[x] = min(low[x] , low[y]); if(low[y] >= dfn[x]) { cnt++; scc[cnt].pb(x); int i; do { i = s.top(); scc[cnt].pb(i); bel[i] = cnt; s.pop(); }while(i!=y); } } else low[x] = min(low[x],dfn[y]); } } vector<int> siz ; vector<int>v; int main() { len = 1; memset(first,-1,sizeof(first)); n = read(); m = read(); for(int i=1;i<=m;i++) { int x = read(); int y = read(); ins(x,y); ins(y,x); } memset(dfn,-1,sizeof(dfn)); memset(low,-1,sizeof(low)); //dfs(3); cnt = 0; for(int i=1;i<=n;i++) if(dfn[i] == -1){while(!s.empty()) s.pop(); dfs(i);} for(int i=2;i<=len;i+=2) { int p = dfn[edge[i].x] > dfn[edge[i].y] ? edge[i].x : edge[i].y; siz[bel[p]].pb(i/2); } for(int i=1;i<=cnt;i++) { if(scc[i].size() == siz[i].size()) for(auto j:siz[i]) v.pb(j); } printf("%d\n",v.size()); sort(v.begin(),v.end()); for(int i=0;i<v.size();i++) printf("%d%c",v[i]," \n"[i==v.size()-1]); return 0; }
相关文章推荐
- Educational Codeforces Round 42 (Rated for Div. 2) D - Merge Equals
- Educational Codeforces Round 39 (Rated for Div. 2)(A-D)(水题 + 模拟 + 贪心模拟 + DP)
- Educational Codeforces Round 33 (Rated for Div. 2)
- Educational Codeforces Round 33 (Rated for Div. 2) F. Subtree Minimum Query (线段树)
- Educational Codeforces Round 35 (Rated for Div. 2) D. Inversion Counting
- Educational Codeforces Round 37 (Rated for Div. 2)-F-SUM and REPLACE(线段树)
- Educational Codeforces Round 34 (Rated for Div. 2) D - Almost Difference
- Educational Codeforces Round 35 (Rated for Div. 2)A,B,C
- Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction(dfs)
- Educational Codeforces Round 36 (Rated for Div. 2)D. Almost Acyclic Graph(正解!!百度的那些拓扑排序现在都已经TLE!)
- Educational Codeforces Round 35 (Rated for Div. 2)
- Educational Codeforces Round 36 (Rated for Div. 2) E. Physical Education Lessons
- Educational Codeforces Round 33 (Rated for Div. 2)A-F
- 【codeforces 】Educational Codeforces Round 36 (Rated for Div. 2)(C.模拟 D.拓扑排序判断环)
- Wannafly挑战赛9+Educational Codeforces Round 37 (Rated for Div. 2)
- Educational Codeforces Round 48 (Rated for Div. 2)——A. Death Note ##
- Educational Codeforces Round 39 (Rated for Div. 2) 946E E. Largest Beautiful Number
- Educational Codeforces Round 36 (Rated for Div. 2) 题解
- Educational Codeforces Round 36 (Rated for Div. 2) E. Physical Education Lessons
- Educational Codeforces Round 33 (Rated for Div. 2)A-F