Codeforces Round #403 (Div. 1, based on Technocup 2017 Finals)
Div1單場我從來就沒上過分,這場又劇毒,半天才打出B,C掛了好幾次最后還FST了,回紫了。
AC:AB Rank:340 Rating:2204-71->2133
?
Div2.B.The Meeting Place Cannot Be Changed
題目大意:n個人,第i個人位于xi,速度為vi,找到一個點使得所有人到這個點的耗時最小,輸出耗時。(n<=60000)
思路:二分答案,知道耗時后可以求出每個人能到達的區間,如果所有區間有交則合法,復雜度O(nlog)。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; char B[1<<26],*S=B,C;int X; inline int read() {while((C=*S++)<'0'||C>'9');for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';return X; } #define MN 60000 int x[MN+5],v[MN+5]; int main() {fread(B,1,1<<26,stdin);int n=read(),i,p;double l=0,r=0x3FFFFFFF,mid,mn,mx,ans;for(i=1;i<=n;++i)x[i]=read();for(i=1;i<=n;++i)v[i]=read();for(p=1;p<=100;++p){mid=(l+r)/2;for(mn=1e18,mx=-1e18,i=1;i<=n;++i)mn=min(mn,x[i]+mid*v[i]),mx=max(mx,x[i]-mid*v[i]);if(mx-mn<1e-12)ans=r=mid;else l=mid;}printf("%.12lf",ans); }?
A.Andryusha and Colored Balloons
題目大意:給出一棵n個點的樹,距離為2以內的點顏色不能相同,求最小染色方案。(n<=200,000)
思路:每個點對他的兒子染色,每個兒子顏色不與他和他父親還有染過的兒子顏色相同即可,復雜度O(n)。
#include<cstdio> char B[1<<26],*S=B,C;int X; inline int read() {while((C=*S++)<'0'||C>'9');for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';return X; } #define MN 200000 struct edge{int nx,t;}e[MN*2+5]; int h[MN+5],en,r[MN+5],fa[MN+5],c[MN+5]; inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;} void dfs(int x) {int i,j=0;for(i=h[x];i;i=e[i].nx)if(e[i].t!=fa[x]){while(c[x]==++j||c[fa[x]]==j);c[e[i].t]=j;fa[e[i].t]=x;dfs(e[i].t);} } int main() {fread(B,1,1<<26,stdin);int n=read(),i,x,y,rt=0;for(i=1;i<n;++i){if(++r[x=read()]>r[rt])rt=x;if(++r[y=read()]>r[rt])rt=y;ins(x,y);ins(y,x);}printf("%d\n",r[rt]+1);dfs(c[1]=1);for(i=1;i<=n;++i)printf("%d ",c[i]); }?
B.Innokenty and a Football League
題目大意:n支球隊要取名,每支球隊有兩種選擇,要求:1.所有球隊名字不能相同;2.如果兩支球隊第一種選擇相同,他們都只能選第二種。(n<=1000)
思路:轉化成2-sat模板題就可以了。2-sat構造解我不是很熟練,打了很久。
#include<iostream> using namespace std; #define MN 1000 #define MV 2000 #define ME 5000000 string s[MN+5][2],sa,sb; struct edge{int nx,t;}e[ME*2+5]; int h[MV+5],en,d[MV+5],l[MV+5],cnt,z[MV+5],zn,inz[MV+5],b[MV+5],bn; int rh[MV+5],r[MV+5],c[MV+5],q[MV+5],qn; inline void ins(int*h,int x,int y){e[++en]=(edge){h[x],y};h[x]=en;} void tj(int x) {d[x]=l[x]=++cnt;inz[z[zn++]=x]=1;for(int i=h[x];i;i=e[i].nx){if(!d[e[i].t])tj(e[i].t);if(inz[e[i].t]&&l[e[i].t]<l[x])l[x]=l[e[i].t];}if(d[x]==l[x])for(++bn;z[zn]!=x;inz[z[zn]]=0)b[z[--zn]]=bn; } int main() {int n,i,j,k;cin>>n;for(i=1;i<=n;++i){cin>>sa>>sb;s[i][0]=s[i][1]=s[i][0]+sa[0]+sa[1];s[i][0]+=sa[2];s[i][1]+=sb[0];}for(i=1;i<=n;++i)for(j=1;j<=n;++j)if(i!=j){if(s[i][0]==s[j][0])ins(h,i,j+n),ins(h,i+n,j+n);if(s[i][0]==s[j][1])ins(h,i,j);if(s[i][1]==s[j][0])ins(h,i+n,j+n);if(s[i][1]==s[j][1])ins(h,i+n,j);}for(i=1;i<=n<<1;++i)if(!d[i])tj(i);for(i=1;i<=n;++i)if(b[i]==b[i+n])return puts("NO"),0;puts("YES");for(i=1;i<=n<<1;++i)for(j=h[i];j;j=e[j].nx)if(b[i]!=b[e[j].t])ins(rh,b[e[j].t],b[i]),++r[b[i]];for(i=1;i<=bn;++i)if(!r[i])q[++qn]=i;for(i=1;i<=qn;++i){if(!c[q[i]]){for(j=1;j<=n;++j)if(b[j]==q[i])c[b[j+n]]=1;for(;j<=n<<1;++j)if(b[j]==q[i])c[b[j-n]]=1;}for(j=rh[q[i]];j;j=e[j].nx)if(!--r[e[j].t])q[++qn]=e[j].t;}for(i=1;i<=n;++i)cout<<(c[b[i]]?s[i][1]:s[i][0])<<endl; }?
C.Underground Lab
題目大意:給出n個點m條邊的無向聯通圖,構造k條長度不超過2n/k(向上取整)的路徑覆蓋所有點。(n,m<=200,000,k<=n)
思路:考慮該圖的一顆生成樹,dfs一遍,進入節點和從子節點回來時都把當前點加入路徑里,就得到一個長度為2n-1的路徑覆蓋,分成k段輸出即可,復雜度O(n)。我輸出寫的巨丑掛了,非常難受。
AC代碼
#include<cstdio> char B[1<<26],*S=B,C;int X; inline int read() {while((C=*S++)<'0'||C>'9');for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';return X; } #define MN 200000 struct edge{int nx,t;}e[MN*2+5]; int f[MN+5],h[MN+5],en,ans[MN*2+5],cnt; int gf(int k){return f[k]?f[k]=gf(f[k]):k;} inline void ins(int x,int y){e[++en]=(edge){h[x],y};h[x]=en;} void dfs(int x,int fa) {ans[++cnt]=x;for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa){dfs(e[i].t,x);ans[++cnt]=x;} } int main() {fread(B,1,1<<26,stdin);int n,m,k,x,y,i,j;n=read();m=read();k=read();while(m--){x=read();y=read();if(gf(x)!=gf(y))f[gf(x)]=gf(y),ins(x,y),ins(y,x);}dfs(1,0);--cnt;for(x=1;x*k<cnt;++x);for(i=1;i<=k;++i){printf("%d ",x);for(j=1;j<=x;++j)printf("%d ",cnt?ans[((i-1)*x+j-1)%cnt+1]:1);puts("");} }?
D.Axel and Marston in Bitland
題目大意:給出一張n個點m條邊的圖,邊權為0或1,按以下方式構造一個01序列:一開始為0,每次將當前串取反加到原串后面(0,01,0110,01101001……),問從點1出發,按這個01序列走對應邊權的邊,最多能走多少步,如果超過10^18輸出-1。(n<=500,m<=2*n^2)
思路:令s[i][0/1]表示長度為2^i的原串/取反串,則有s[i+1][0]=s[i][0]+s[i][1],s[i+1][1]=s[i][1]+s[i][0],我們把原圖按這個方式bitset加速倍增一下,然后DP就可以了,復雜度O(n^3/32*log10^18),時限5s而且cf機子快,非常科學。
#include<cstdio> #include<cstring> #include<bitset> #include<algorithm> #include<iostream> using namespace std; inline int read() {int x;char c;while((c=getchar())<'0'||c>'9');for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';return x; } #define MN 500 #define MK 60 #define INF 1000000000000000000LL bitset<MN+5> g[MK+5][2][MN+5]; long long f[MK+5][MN+5][2],ans; int main() {int n,m,i,j,k,x,y;n=read();m=read();while(m--){x=read();y=read();g[0][read()][x][y]=1;}for(k=0;k<MK;++k)for(i=1;i<=n;++i)for(j=1;j<=n;++j){if(g[k][0][i][j])g[k+1][0][i]|=g[k][1][j];if(g[k][1][i][j])g[k+1][1][i]|=g[k][0][j];}memset(f,128,sizeof(f));f[k+1][1][0]=0;for(k=MK;k>=0;--k){for(i=1;i<=n;++i)f[k][i][0]=f[k+1][i][0],f[k][i][1]=f[k+1][i][1];for(i=1;i<=n;++i)for(j=1;j<=n;++j){if(g[k][0][i][j])f[k][j][1]=max(f[k][j][1],f[k+1][i][0]+(1LL<<k));if(g[k][1][i][j])f[k][j][0]=max(f[k][j][0],f[k+1][i][1]+(1LL<<k));}}for(i=1;i<=n;++i)ans=max(ans,max(f[0][i][0],f[0][i][1]));cout<<(ans>INF?-1:ans); }?
轉載于:https://www.cnblogs.com/ditoly/p/CF403.html
總結
以上是生活随笔為你收集整理的Codeforces Round #403 (Div. 1, based on Technocup 2017 Finals)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决nginx重启“var/run/ng
- 下一篇: ViewTreeObserver视图树观