10月集训test20

来源:互联网 发布:人工智能的利弊英语 编辑:程序博客网 时间:2024/05/15 09:39

有几天没有写总结了,后面应该会补上之前的总结。
第一次全场爆零呵呵呵呵。。。。。。。。。
第一题错在了最后答案没有%mod再输出(最好从头到尾都%mod);
第二题大概是没有很好地把握时间复杂度;
第三题嘛。。我是真的不知道怎么WA了,大概是爆int了?
上题。

1.数列求和

理解题意并不难,就是将原数列的每一个子段内部相乘,每一个子段之间将相乘的积相加。不难看出(所以这里真的不难看出吗。。。为什么我就是没有看出。。。),考虑所有右端点为x的答案,可以发现答案为所有右端点为x-1的答案加1,再乘a。但是由于后面到了1e18的精度,所以用快速乘即可。

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;int n;long long p,ans,now;long long x;inline long long read(){    long long i=0;char c;    for(c=getchar();c<'0'||c>'9';c=getchar());    for(;c>='0'&&c<='9';c=getchar())        i=(i<<1)+(i<<3)+c-'0';    return i;}inline long long ksc(long long x,long long y){    long long ans=0,aa=x;    while(y)                          //快速乘。    {        if(y&1)            ans=(ans+aa)%p;        aa=(aa+aa)%p,y>>=1;    }    return ans;}int main(){    //freopen("sum.in","r",stdin);    //freopen("sum.out","w",stdout);    n=read(),p=read();    ans=0;now=0;    for(int i=1;i<=n;i++)    {        x=read();        now=ksc(now+1,x);        ans=(ans+now)%p;    }       printf("%lld\n",ans);    return 0;}

2.路径统计

可以看出,每一个连通块里面,都是一个环再加上环上的许许多多奇形怪状的树,不同的连通块则不能连通。环上点对答案的贡献很好写,然后就是树边,下方的子树与上方路径上的点和环上点的路径。
要缩点呐,dfs其实就是dijkstra的思想。

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>#include<vector>using namespace std;struct node{    int next,to,w;}bian[500010];const int p=1000000007;int n,tot,cnt,num,top,idx;int first[500010],len[500010],t[500010];int dfn[500010],low[500010],stk[500010];int id[500010],size[500010],dis[500010];long long sum[500010],val[500010],ans;bool flag[500010];vector<int>f[500010];inline int read(){    int i=0;char c;    for(c=getchar();c<'0'||c>'9';c=getchar());    for(;c>='0'&&c<='9';c=getchar())        i=(i<<1)+(i<<3)+c-'0';    return i;}inline void add(int x,int y,int z){    bian[++tot].next=first[x];    first[x]=tot;    bian[tot].to=y;    bian[tot].w=z;}inline void tarjan(int u){    dfn[u]=low[u]=++idx;    stk[++top]=u;flag[u]=true;    int v=t[u];    if(!dfn[v])    {        tarjan(v);        low[u]=min(low[u],low[v]);    }    else        if(flag[v])            low[u]=min(low[u],dfn[v]);    if(low[u]==dfn[u])    {        ++num;        v=stk[top];        while(u!=v)        {            id[v]=num;size[num]++;            f[num].push_back(v);            top--;flag[v]=false;            v=stk[top];        }        id[v]=num;size[num]++;        f[num].push_back(v);        top--;flag[v]=false;    }}inline void dfs(int u,int cnt){    flag[u]=true;    ans=((ans-1ll*(n-cnt)*size[u])%p)%p;    for(int i=first[u];i;i=bian[i].next)    {        int v=bian[i].to;        if(!flag[v])            dfs(v,cnt+size[v]);        ans=(ans+1ll*size[v]*cnt%p*bian[i].w%p)%p;        size[u]+=size[v];    }}inline void zql(int i){    int u;    reverse(f[i].begin(),f[i].end());    for(int j=0;j<size[i];j++)        u=f[i][j],val[f[i][0]]=(val[f[i][0]]+1ll*(size[i]-j)*len[f[i][j]]%p)%p;    for(int j=1;j<size[i];j++)        u=f[i][j],val[f[i][j]]=(val[f[i][j-1]]+sum[i]-1ll*size[i]%p*len[f[i][j-1]]%p)%p;    for(int j=0;j<size[i];j++)        u=f[i][j],val[f[i][j]]=(val[f[i][j]]-sum[i])%p;}int main(){    //freopen("road.in","r",stdin);    //freopen("road.out","w",stdout);    int _q=50<<20;    char *_p=(char*)malloc(_q)+_q;    __asm__("movl %0, %%esp\n"::"r"(_p));    //改变栈空间的大小。     n=read();    for(int i=1;i<=n;i++)        t[i]=read(),len[i]=read();    for(int i=1;i<=n;i++)        if(!dfn[i])            tarjan(i);    for(int i=1;i<=n;i++)        if(id[i]==id[t[i]])            sum[id[i]]=(sum[id[i]]+len[i])%p;        else            add(id[t[i]],id[i],len[i]);    for(int i=1;i<=num;i++)    {        if(size[i]==1) continue;        ans=(ans+1ll*size[i]*(size[i]-1)/2%p*sum[i]%p)%p;        zql(i);    }           memset(flag,0,sizeof(flag));            for(int i=1;i<=num;i++)        if(!flag[i])            dfs(i,size[i]);    for(int i=1;i<=n;i++)        if(id[i]!=id[t[i]])            ans=(ans+1ll*size[id[i]]*val[t[i]]%p)%p;    cout<<(ans%p+p)%p;    return 0;}

3.小店购物

唔说实话感觉这道题还要比上一道题简单一些。
看完题就会发现,需要一个数据结构能够支持单点修改,区间最值查询的,用线段树就好了。然而为了减少复杂度,需要离散化。

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>using namespace std;struct node1{    long long p,w;    int num,t;}wu[2000010];struct node2{    int k;    long long x,y,z;}qu[1000010];const long long inf=1E+17;int n,m,tot,bz;int to[2000010],f[2000010];long long tree[2000010];inline bool comp(const node1 &a,const node1 &b){    if(a.w==b.w)        return a.p<b.p;    return a.w>b.w;}inline void build(int root,int l,int r){    if(l==r)    {        if(!wu[l].t)            tree[root]=wu[l].p;        else            tree[root]=inf;        return;    }    int mid=(l+r)/2;    build(root*2,l,mid);    build(root*2+1,mid+1,r);    tree[root]=min(tree[root*2],tree[root*2+1]);}inline void que(int root,int l,int r,int t){    if(l==r)    {        bz=l;return;    }    int mid=(l+r)/2;    if(tree[root*2]<=t)        que(root*2,l,mid,t);    else if(tree[root*2+1]<=t)        que(root*2+1,mid+1,r,t);}inline void zql(int root,int l,int r,int t){    if(l==r)    {        if(t==l)            tree[root]=inf;        return;    }    int mid=(l+r)/2;    if(t<=mid)        zql(root*2,l,mid,t);    else        zql(root*2+1,mid+1,r,t);    tree[root]=min(tree[root*2],tree[root*2+1]);}inline void czh(int root,int l,int r,int t){    if(l==r)    {        if(t==l)            tree[root]=wu[l].p;        return;    }    int mid=(l+r)/2;    if(t<=mid)        czh(root*2,l,mid,t);    else        czh(root*2+1,mid+1,r,t);    tree[root]=min(tree[root*2],tree[root*2+1]);}int main(){    //freopen("shopping.in","r",stdin);    //freopen("shopping.out","w",stdout);    ios::sync_with_stdio(false);    cin.tie(NULL);    cin>>n>>m;    for(int i=1;i<=n;i++)    {        cin>>wu[++tot].w;        cin>>wu[tot].p;        wu[tot].num=i;    }    for(int i=1;i<=m;i++)    {        cin>>qu[i].k;        if(qu[i].k==2)            cin>>qu[i].x;        else        {            cin>>qu[i].x>>qu[i].y>>qu[i].z;            wu[++tot].w=qu[i].y;            wu[tot].p=qu[i].z;            wu[tot].num=qu[i].x;            wu[tot].t=i;        }    }    sort(wu+1,wu+tot+1,comp);    for(int i=1;i<=tot;i++)        to[wu[i].t]=i;    for(int i=1;i<=tot;i++)        if(!wu[i].t)            f[wu[i].num]=i;    build(1,1,tot);    for(int i=1;i<=m;i++)    {        if(qu[i].k==2)        {            long long ans=0;            while(qu[i].x>=tree[1])            {                que(1,1,tot,qu[i].x);                ans+=qu[i].x/wu[bz].p*wu[bz].w;                qu[i].x-=qu[i].x/wu[bz].p*wu[bz].p;            }            cout<<ans<<"\n";        }        else        {            zql(1,1,tot,f[qu[i].x]);            czh(1,1,tot,to[i]);            f[qu[i].x]=to[i];        }    }    return 0;}

以上。
来自2017.11.8.

——我认为 return 0,是一个时代的终结。

原创粉丝点击