1. 程式人生 > >Codeforces Round #526 Div. 1 自閉記

Codeforces Round #526 Div. 1 自閉記

  日常猝死。

  A:f[i]表示子樹內包含根且可以繼續向上延伸的路徑的最大價值,統計答案考慮合併兩條路徑即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define inf 10000000000000000ll
char getc(){char
c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='
9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,p[N],t; ll f[N][2],a[N],ans; struct data{int to,nxt,len; }edge[N<<1]; void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} void dfs(int k,int from) { f[k][1]=f[k][0]=a[k]; ll mx
=-inf,mx2=-inf; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=from) { dfs(edge[i].to,k); ll x=f[edge[i].to][1]-edge[i].len; if (x>mx) mx2=mx,mx=x; else if (x>mx2) mx2=x; } f[k][1]=max(mx+a[k],a[k]); f[k][0]=max(f[k][0],f[k][1]); f[k][0]=max(f[k][0],a[k]+mx+mx2); } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<n;i++) { int x=read(),y=read(),z=read(); addedge(x,y,z),addedge(y,x,z); } dfs(1,1); for (int i=1;i<=n;i++) ans=max(ans,f[i][0]),ans=max(ans,f[i][1]); cout<<ans; return 0; }
View Code

  B:每次一有還不錯的開局馬上就自閉了。一直都在正解附近徘徊愣是過了1h才pp。沒救了。如果一個字串最早在第i位與其他字串都不同,其可以提供n-i+1的貢獻。那麼貪心的儘量讓高位不同。問題在於如何統計貢獻。將a看成0,b看成1後,變成兩個二進位制數。對於每一個字首,將兩個字首二進位制數相減得到的就是這段字首的不同串數量。減去上一位的就可以得到在該位新出現的字首個數。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[N],b[N];
ll ans,tot,f[N],m;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
#endif
    n=read(),m=read();
    for (int i=1;i<=n;i++) a[i]=getc()-'a';
    for (int i=1;i<=n;i++) b[i]=getc()-'a';
    ll x=0,y=0;
    for (int i=1;i<=n;i++)
    {
        x=x<<1|a[i],y=y<<1|b[i];
        f[i]=y-x+1;
        ans+=1ll*(min(m,f[i])-f[i-1])*(n-i+1);
        if (f[i]>m) break;
    }
    cout<<ans;
    return 0;
}
View Code

  E:E過的人最多當然是看E了。冷靜了一會發現排個序之後就成了一個序列問題,可以瞎dp了,式子寫出來發現一發斜率優化就完了。然後我也不知道發生了啥。

  按橫座標從小到大排序,那麼如果選擇了某個矩形,其後面的矩形產生的貢獻就與前面的矩形無關了。於是有一發顯然的dp,即設f[i]為選擇第i個矩形時前i個矩形的最大價值,有f[i]=max{f[j]+(xi-xj)yi-ai}。式子是裸的不能再裸的斜率優化,就做完了。鬼知道發生了啥啊?

  然後終測完了終於看到了第三個點是啥……woc ai是可以爆int的啊?怎麼想的到啊?以後乾脆還是都define int long long算了反正cf機子不虛……心態爆炸。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define ll long long
#define N 1000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
ll read()
{
    ll x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,q[N];
ll f[N];
struct data
{
    int x,y;ll v;
    bool operator <(const data&a) const
    {
        return x<a.x;
    }
}a[N];
long double calc(ll x,ll y)
{
    return (long double)(f[y]-f[x])/(a[y].x-a[x].x);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("e.in","r",stdin);
    freopen("e.out","w",stdout);
#endif
    n=read();
    for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].v=read();
    sort(a+1,a+n+1);
    int head=1,tail=1;q[1]=0;
    for (int i=1;i<=n;i++)
    {
        ll t=1ll*a[i].y*a[i].x-a[i].v;
        while (head<tail&&calc(q[head],q[head+1])>a[i].y) head++;
        f[i]=f[q[head]]+t-1ll*a[q[head]].x*a[i].y;
        while (head<tail&&calc(q[tail-1],q[tail])<calc(q[tail],i)) tail--;
        q[++tail]=i;
    }
    ll ans=0;
    for (int i=1;i<=n;i++) ans=max(ans,f[i]);
    cout<<ans;
    return 0;
}
View Code

  完全能翻的場還是莫名其妙就跪掉了,自閉。

  result:rank 146 rating -3