Educational Codeforces Round 55 (Rated for Div. 2)
阿新 • • 發佈:2018-11-29
sizeof force () codeforce sub ova == break eof
Educational Codeforces Round 55 (Rated for Div. 2)
鏈接
A Vasya and Book
傻逼題。。註意判邊界。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<cmath> using namespace std; typedef long long ll; int t,n,x,y,d; int main() { scanf("%d",&t); while(t--) { scanf("%d%d%d%d",&n,&x,&y,&d); int sxz=abs(x-y); if(sxz%d==0) { printf("%d\n",sxz/d); continue; } int ans=0x7fffffff; if((y-1)%d==0) ans=min(ans,(x==1?0:(int)ceil((double)(x-1)/d))+(y-1)/d); if((n-y)%d==0) ans=min(ans,(x==n?0:(int)ceil((double)(n-x)/d))+(n-y)/d); if(ans==0x7fffffff) printf("-1\n"); else printf("%d\n",ans); } return 0; }
B Vova and Trophies
還是傻逼題。。還是要判好邊界。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<cmath> using namespace std; typedef long long ll; const int Maxn=110000; int n,a[Maxn],l[Maxn],ok[Maxn],tot; char getach() { char ch=getchar(); while(ch!=‘G‘&&ch!=‘S‘) ch=getchar(); return ch; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { if(getach()==‘G‘) { a[i]=1; if(i>2&&a[i-1]==0&&a[i-2]) ok[tot]=1; l[tot]++; } else if(a[i-1]) tot++; } if(a[n]==1) tot++; if(tot==1) { printf("%d",l[0]); return 0; } int ans=0; for(int i=0;i<tot;i++) { ans=max(ans,l[i]+1); if(ok[i]) { if(tot==2) ans=max(ans,l[i]+l[i-1]); else ans=max(ans,l[i]+l[i-1]+1); } } printf("%d",ans); return 0; }
C Multi-Subject Competition
開n個堆就好了,用隊列存著目前堆非空且和不為負數的堆分別是那幾個,時間復雜度\(O(n \log n)\)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<cmath> using namespace std; typedef long long ll; const int Maxn=110000; int n,m,c[Maxn],b[Maxn],ans,x,y,tot; priority_queue<int> q[Maxn]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); q[x].push(y); } for(int i=1;i<=m;i++) if(!q[i].empty()&&q[i].top()>0) { b[++tot]=q[i].top(); c[tot]=i; q[i].pop(); } int num=0; for(int i=1;i<=tot;i++) num+=b[i]; ans=max(ans,num); while(tot) { int sxz=tot; tot=0; num=0; for(int i=1;i<=sxz;i++) if(!q[c[i]].empty()&&b[i]+q[c[i]].top()>0) { b[++tot]=b[i]+q[c[i]].top(); c[tot]=c[i]; q[c[i]].pop(); } for(int i=1;i<=tot;i++) num+=b[i]; ans=max(ans,num); } printf("%d",ans); return 0; }
D Maximum Diameter Graph
這個題可以貪心,把所有的點按照度數限制排個序,然後枚舉直徑的長度,直徑兩邊選度數限制最小的,其余的點選度數限制最大的,然後把其他的點掛上就好了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int Maxn=110000;
int n,m,a[Maxn],b[Maxn];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=i;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[j]>a[i]) {
swap(a[i],a[j]);
swap(b[i],b[j]);
}
for(int i=n-2;i>=1;i--) {
int num=0;
for(int j=1;j<=i;j++)
if(a[j]>=2) num+=a[j]-2;
else {
num=-1;
break;
}
if(num>=n-i-2) {
printf("YES %d\n",i+1);
printf("%d\n",n-1);
printf("%d %d\n",b[n],b[1]);
printf("%d %d\n",b[n-1],b[i]);
for(int j=1;j<i;j++) printf("%d %d\n",b[j],b[j+1]);
int temp=1;
for(int j=i+1;j<=n-2;j++)
if(a[temp]>2) {
a[temp]--;
printf("%d %d\n",b[temp],b[j]);
}
else {
while(a[temp]==2) temp++;
a[temp]--;
printf("%d %d\n",b[temp],b[j]);
}
return 0;
}
}
puts("NO");
return 0;
}
E Increasing Frequency
這道題是傻逼貪心,我竟然沒看出來。。
大概就是記一下c出現個數的前綴和,然後枚舉其他的每個數,把這個數在數列中出現的位置排個序,從前往後掃一遍,維護左右端點,然後對於一個區間,如果在這個區間中c的出現次數比這個數多,那就把這個區間扔掉。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int Maxn=510000;
const double eps=1e-9;
int n,c,x,a[Maxn],ans;
priority_queue<int,vector<int>,greater<int> >h[Maxn];
int main() {
// freopen("test.in","r",stdin);
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++) {
scanf("%d",&x);a[i]=a[i-1];
if(x==c) a[i]++;
h[x].push(i);
}
for(int i=1;i<=500000;i++)
if(i!=c&&!h[i].empty()) {
int sxz=0,zhy=1,last=h[i].top();
h[i].pop();
ans=max(ans,zhy);
while(!h[i].empty()) {
int temp=h[i].top();
h[i].pop();
sxz+=a[temp]-a[last];
zhy++;
if(sxz>=zhy) {
sxz=0;
zhy=1;
}
ans=max(ans,zhy-sxz);
last=temp;
}
}
printf("%d",ans+a[n]);
return 0;
}
F
毒瘤。。。
G Petya and Graph
這個題是個傻逼網絡流。。我竟然沒看出來。
大概就是最小割建圖,把每個點和每個邊建點,每個邊從他的兩個端點連邊,流量為正無窮;從原點向所有的點連邊,流量為點的點權;從所有邊向匯點連邊,流量為邊權。
memset(b,0,sizeof(b));
b[s]=1;
while(!q.empty()) {
int now=q.front();q.pop();
for(int i=first[now];i;i=nxt[i])
if(w[i]&&b[to[i]]==0) {
b[to[i]]=b[now]+1;
q.push(to[i]);
}
}
return b[t];
}
ll dfs(int root,int flow) {
if(root==t) return flow;
for(int i=first[root];i;i=nxt[i])
if(w[i]&&b[to[i]]==b[root]+1) {
int temp=dfs(to[i],min(flow,w[i]));
if(temp) {
w[i]-=temp;
w[i^1]+=temp;
return temp;
}
}
return 0;
}
ll dinic() {
ll ans=0,temp;
while(bfs())
while(temp=dfs(s,inf))
ans+=temp;
return ans;
}
int main() {
// freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
s=0,t=n+m+1;
for(int i=1;i<=n;i++) {
scanf("%I64d",&x);
add(s,i,x);
}
for(int i=1,sxz=n+1;i<=m;i++,sxz++) {
scanf("%d%d%I64d",&u,&v,&x);
add(u,sxz,inf);
add(v,sxz,inf);
add(sxz,t,x);
ans+=x;
}
printf("%I64d",ans-dinic());
return 0;
}
Educational Codeforces Round 55 (Rated for Div. 2)