【NOIP模拟8.8】

T1 expedition

离散化后记录每一种士兵的出现次数计算即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;

LL n,a[100010],b[100010],c[100010];
LL cnt[100010],ans;

int main()
{
    freopen("expedition.in","r",stdin);
    freopen("expedition.out","w",stdout);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)   scanf("%lld%lld",&a[i],&b[i]),c[i]=b[i];
    sort(c+1,c+n+1);
    int m=unique(c+1,c+n+1)-c-1;
    for(int i=1;i<=n;i++)   b[i]=lower_bound(c+1,c+m+1,b[i])-c,cnt[b[i]]+=a[i];
    for(int i=1;i<=n;i++)   ans+=cnt[b[i]]*cnt[b[i]],cnt[b[i]]=0;
    printf("%lld",ans);
    return 0;
}

T2 simplify

相当于一个多项式的中缀表达式求值,一个数组其实就可以用来表示一个多项式,数组的每一项是多项式每一项的系数,所以只需要手动模拟一下多项式加法,减法,乘法,递归计算的复杂度 O(n4) ,如果用两个栈分别记录运算的多项式和符号,根据符号的优先级计算,复杂度是 O(n3)
PS:拉格朗日插值法可以做到 O(n2) ,但实际上和上述算法时间是接近的

//by sdfzchy
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010,mod=10007;
char s[1010];
int len,optop,top,op[1010];
struct info
{
    int len,a[501];
    info(){len=0,memset(a,0,sizeof(a));}
    void reset(){while(len&&!a[len]) len--;}
}stack[1010];

info operator + (info a,info b)
{
    info c;
    c.len=max(a.len,b.len);
    for(int i=0;i<=c.len;i++) c.a[i]=a.a[i]+b.a[i];
    c.reset();
    return c;   
}

info operator - (info a,info b)
{
    info c;
    c.len=max(a.len,b.len);
    for(int i=0;i<=c.len;i++) c.a[i]=a.a[i]-b.a[i];
    c.reset();
    return c;
}

info operator * (info a,info b)
{
    info c;
    c.len=a.len+b.len;
    for(int i=0;i<=a.len;i++)
        for(int j=0;j<=b.len;j++)
            (c.a[i+j]+=a.a[i]*b.a[j])%=mod;
    c.reset();
    return c;       
}

int prio(char a)
{
    if(a=='+'||a=='-') return 1;
    if(a=='*') return 2;
    if(a=='(') return 0;
}

void calc()
{
    if(op[optop]=='+') stack[top-1]=stack[top-1]+stack[top];
    else if(op[optop]=='-') stack[top-1]=stack[top-1]-stack[top];
    else if(op[optop]=='*') stack[top-1]=stack[top-1]*stack[top];
    optop--;top--;
}

void pause(){return;}
int main()
{
    freopen("simplify.in","r",stdin);
    freopen("simplify.out","w",stdout);
    scanf("%s",s+1);
    len=strlen(s+1);
    for(int i=1;i<=len;i++)
    {
        if(s[i]=='(')   op[++optop]='(';
        else if(s[i]==')')
        {
            pause();
            while(op[optop]!='(') calc();
            optop--;
        }
        else if(s[i]=='x')
        {
            info a;
            a.a[1]=1;
            a.len=1;
            memset(stack[top+1].a,0,sizeof(stack[top+1].a));
            stack[++top]=a;
        }
        else if(s[i]>='0'&&s[i]<='9')
        {
            info a;
            int x=0;
            while(s[i]>='0'&&s[i]<='9') x=x*10+s[i++]-'0';
            i--;
            a.a[0]=x;
            memset(stack[top+1].a,0,sizeof(stack[top+1].a));
            stack[++top]=a;
        }
        else if(s[i]=='+'||s[i]=='-')
        {
            if(i==1||(s[i-1]=='('))
            {
                int flag=(s[i++]=='+')?1:(-1);
                if(s[i]=='x')
                {
                    info a;
                    a.a[1]=flag;
                    a.len=1;
                    memset(stack[top+1].a,0,sizeof(stack[top+1].a));    
                    stack[++top]=a;
                }
                if(s[i]>='0'&&s[i]<='9')
                {
                    info a;
                    int x=0;
                    while(s[i]>='0'&&s[i]<='9') x=x*10+s[i++]-'0';
                    i--;
                    a.a[0]=x*flag;
                    memset(stack[top+1].a,0,sizeof(stack[top+1].a));
                    stack[++top]=a;
                }
            }
            else 
            {
                while(prio(s[i])<=prio(op[optop])) calc();
                op[++optop]=s[i];
            }
        }
        else if(s[i]=='*')
        {
            while(prio(s[i])<=prio(op[optop])) calc();
            op[++optop]=s[i];
        }
    }
    while(optop) calc();
    cout<<stack[1].len<<endl;
    for(int i=0;i<=stack[1].len;i++)
        cout<<(stack[1].a[i]%mod+mod)%mod<<endl;
    return 0;
}

T3 production

正反向各建一次图跑SPFA即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;

const int N=3010;
const int M=100010;
int head[N],ecnt,eecnt,hhead[N],n,m,dis[N],ddis[N],q;
bool vis[N];
struct edge
{
    int to,nxt,dis;
}e[M],ee[M];

void add_edge(int u,int v,int w)
{
    e[++ecnt].nxt=head[u];
    e[ecnt].to=v;
    e[ecnt].dis=w;
    head[u]=ecnt;

    ee[++eecnt].nxt=hhead[v];
    ee[eecnt].to=u;
    ee[eecnt].dis=w;
    hhead[v]=eecnt;
}

void SPFA()
{
    int v,u;
    queue<int> q;
    q.push(1);
    dis[1]=0;
    vis[1]=1;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=e[i].nxt)
        {
            v=e[i].to;
            if(dis[u]+e[i].dis<dis[v])
            {
                dis[v]=dis[u]+e[i].dis;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

void SSPFA()
{
    int v,u;
    queue<int> q;
    q.push(1);
    ddis[1]=0;
    vis[1]=1;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=hhead[u];i;i=ee[i].nxt)
        {
            v=ee[i].to;
            if(ddis[u]+ee[i].dis<ddis[v])
            {
                ddis[v]=ddis[u]+ee[i].dis;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

int main()
{
    freopen("production.in","r",stdin);
    freopen("production.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1,u,v,w;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        add_edge(u,v,w);
    }
    memset(dis,0x3f,sizeof(dis));
    memset(ddis,0x3f,sizeof(ddis));
    SPFA();
    SSPFA();
    scanf("%d",&q);
//  for(int i=1;i<=n;i++) cout<<dis[i]<<" "<<ddis[i]<<endl;
    for(int i=1,u,v;i<=q;i++)
    {
        scanf("%d%d",&u,&v);
        int tmp=ddis[u]+dis[v];
        if(tmp>=1061109567) printf("-1\n");
        else printf("%d\n",tmp);
    }
    return 0;
}

PS:一套水题…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值