11.7 CSP赛前集训小结

11.7 CSP赛前集训小结

今天是单赛日

1.上午的订正:没啥好说的

昨天的T1,稍微写下思路,维护高度差然后直接分情况讨论会很让人自闭,再加上符号+-和变化量的不同,会爆炸,那么不妨将之间的变化先减去,算上答案后再再加回来即可,正难则反的道理。

#include<stdio.h>
#include<bits/stdc++.h>
#define maxn 200005
using namespace std;
long long Ht[maxn];
long long n,q,s,t;
long long Getdel(long long x)
{
   return x > 0 ? x * s : x * t; 
}
long long T=0;
int main()
{
    scanf("%lld%lld%lld%lld",&n,&q,&s,&t);
    s=-s;
    t=-t; 
    for(long long i=0;i<=n;i++)
    scanf("%lld",&Ht[i]);
    
    for(long long i=n;i;i--)
    Ht[i]-=Ht[i-1];
    
    for(long long i=1;i<=n;i++)
    
    T+=Getdel(Ht[i]);
    long long x,y;
    long long temp;
    while(q--)
    {
        scanf("%lld%lld%lld",&x,&y,&temp);
        T-=Getdel(Ht[x]);
        T-=Getdel(Ht[y+1]);
        Ht[x]+=temp;
        if(y+1<=n)
        Ht[y+1]-=temp;
        T+=Getdel(Ht[x]);
        if(y+1<=n)
        T+=Getdel(Ht[y+1]);
        printf("%lld\n",T);
    }
}

然后就是董神讲的两道题,一道是再求最短路时DP一下,另一道则是口胡了一堆破数学公式。。然后发现题目看错了233333333

第一道的代码(本人没调,这是LCFjulao的代码)

#include<stdio.h>
#include<queue>
using namespace std;

#define INF 1000000000

int End[100005],Next[100005],Len[100005],Last[10004],tot;
int n,k,Dis[10004][12];
bool Inqueue[10005][12];
struct node{int p,t;};
bool operator<(node a,node b){return Dis[a.p][a.t]>Dis[b.p][b.t];}
priority_queue<node>q;

void Link(int x,int y,int l)
{
    tot++;
    End[tot]=y;
    Len[tot]=l;
    Next[tot]=Last[x];
    Last[x]=tot;
}

void DJ(int x)
{
    int i,j,t,y;
    node a;
    for(i=0;i<=n;i++)for(j=0;j<=k;j++)Dis[i][j]=INF;
    Dis[x][0]=0;
    a.p=x,a.t=0;
    q.push(a);
    Inqueue[x][0]=true;
    while(q.size())
    {
        x=q.top().p,t=q.top().t;
        q.pop();
        Inqueue[x][t]=false;
        for(i=Last[x];i;i=Next[i])
        {
            y=End[i];
            if(Dis[x][t]+Len[i]<=Dis[y][t])
            {
                Dis[y][t]=Dis[x][t]+Len[i];
                if(!Inqueue[y][t])
                {
                    a.p=y,a.t=t;
                    q.push(a);
                    Inqueue[y][t]=true;
                }
            }
            if(t<k&&Dis[x][t]<Dis[y][t+1])
            {
                Dis[y][t+1]=Dis[x][t];
                if(!Inqueue[y][t+1])
                {
                    a.p=y,a.t=t+1;
                    q.push(a);
                    Inqueue[y][t+1]=true;
                }
            }
        }
    }
}

int main()
{
    int m,s,t,a,b,c,i,ans=INF;
    scanf("%d %d %d",&n,&m,&k);
    scanf("%d %d",&s,&t);
    for(i=1;i<=m;i++)
    {
        scanf("%d %d %d",&a,&b,&c);
        Link(a,b,c);
        Link(b,a,c);
    }
    DJ(s);
    for(i=0;i<=k;i++)ans=min(ans,Dis[t][i]);
    printf("%d",ans);
}

 然后没事干,然后就水了道树DP的题(本来该用DP做的)

#include<bits/stdc++.h>
#define maxn 10005
#define inf 999999999
using namespace std;
/*
结论:树上任意一点的最长距离一定是到直径某一端点的距离
因此此题可以先通过该结论求出树的直径
求法:找任意一个点求出该点的最远距离点T
由结论可知T一定是树直径的端点,再求离T最远的点S,由结论又可知S也是端点
所以ST即为树的直径,然后再用一遍结论,本题中每个点的最远距离即为max(dis【S】,dis【T】);
要用到两次结论做本题,有点意思 
*/ 
struct node
{
    int To,Len;
};
vector<node> Map[maxn];
int Max_Dis=-inf;
int S=0;
int Type=0;
int Dis_S[maxn];
int Dis_T[maxn];
void Dfs1(int pos,int fa,int Dis)
{
//    cout<<Dis<<endl;
    if(Type==1)
    {
        Dis_S[pos]=Dis;
    }
    if(Type==2)
    {
        Dis_T[pos]=Dis;
    }
    if(Dis>=Max_Dis)
    {
        S=pos;
        Max_Dis=Dis;
    }
    for(int i=0;i<Map[pos].size();i++)
    {
        if(Map[pos][i].To!=fa)
        Dfs1(Map[pos][i].To,pos,Dis+Map[pos][i].Len);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    node temp;
    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        temp.To=x;
        temp.Len=y;
        Map[i+1].push_back(temp);
        temp.To=i+1;
        Map[x].push_back(temp);
    }
    Type=0;
    Dfs1(1,1,0);
    int SS=S;
    Max_Dis=-inf;
    S=0;
    Type=1;
    Dfs1(SS,SS,0);
    int TT=S;
    Type=2;
    Max_Dis=-inf;
    Dfs1(TT,TT,0);
    for(int i=1;i<=n;i++)
    {
        printf("%d\n",max(Dis_T[i],Dis_S[i]));
    }
}

猜你喜欢

转载自www.cnblogs.com/pveds/p/11811306.html