8
7
2015
3

BZOJ 2456: mode

Description

给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数。

数据范围:  100%的数据,n<=500000,数列中每个数<=maxlongint。

数据范围太大,于是在网上找的了一个比较神奇的找众数的方法:

因为题中规定了众数一定多于二分之一,所以可以每次搜到不同的数都抵消,最后剩下的一定是最多的那个;

代码:


/**************************************************************
    Problem: 2456
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:372 ms
    Memory:804 kb
****************************************************************/
 
 
#include<cstdio>
 
using namespace std;
 
int n,p;
int x,a;
int main()
{
    scanf("%d",&n);
    while(n--)
    {
     
        scanf("%d",&a);
        if(!p)
        {
            p=1;
            x=a;
        }
        else
        {
            if(x==a) p++;
            else p--;
        }
    }
    printf("%d",x);
    return 0;
}
 
Category: 未分类 | Tags:
8
7
2015
1

BZOJ 1801: [Ahoi2009]chess 中国象棋

Description

在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.
 
一道DP 开始向一般的状态压缩DP ,结果数组开不下。。。
用两维分别表示有两个棋子的列数和一个棋子的列数,没有棋子的可以用总列数减去其余两种;
分了5种转移的情况:
1.一个棋子的加一个;
2.零个棋子的加一个;
3.两列一个棋子的分别加一;
4.两列零个棋子分别加一;
5.一列零个棋子一列一个棋子分别加一;
分情况转移就行了。
/**************************************************************
    Problem: 1801
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:292 ms
    Memory:1444 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
long long f[2][105][105];
 
int n,m;
const int mod=9999973;
 
int main()
{
//  freopen("1.txt","r",stdin);
    scanf("%d%d",&n,&m);
    f[0][0][0]=1;
    for(int i=0;i<n;++i)
    {
        memset(f[~i&1],0,sizeof(f[i&1]));
        for(int j=0;j<=m;++j)
            for(int k=0;k+j<=m;++k)
            {
                int l=m-k-j;
                 
                f[~i&1][j][k]+=f[i&1][j][k],f[~i&1][j][k]%=mod;
                if(j>1)f[~i&1][j-2][k+2]+=(f[i&1][j][k]*j*(j-1))/2,f[~i&1][j-2][k+2]%=mod;
                if(j>0)f[~i&1][j-1][k+1]+=f[i&1][j][k]*j,f[~i&1][j-1][k+1]%=mod; 
                if(l>0)f[~i&1][j+1][k]+=f[i&1][j][k]*l,f[~i&1][j+1][k]%=mod;
                if(l>1)f[~i&1][j+2][k]+=(f[i&1][j][k]*l*(l-1))/2,f[~i&1][j+2][k]%=mod;
                if(l>0&&j>0)f[~i&1][j][k+1]+=f[i&1][j][k]*l*j,f[~i&1][j][k+1]%=mod;
            }
    }
    long long ans=0;
    for(int j=0;j<=m;++j)
        for(int k=0;k+j<=m;++k)
        {
            ans+=f[n&1][j][k];
            ans%=mod;
        }
    printf("%lld",ans);
    return 0;
}

 

Category: 未分类 | Tags:
7
27
2015
0

BZOJ 1806: [Ioi2007]Miners 矿工配餐

Description

现有两个煤矿,每个煤矿都雇用一组矿工。采煤工作很辛苦,所以矿工们需要良好饮食。每当一辆食品车到达煤矿时,矿工们便会产出一定数量的煤。有三种类型的食品车:肉车,鱼车和面包车。 矿工们喜欢变化的食谱。如果提供的食品能够不断变化,他们的产煤量将会增加。每当一个新的食品车到达煤矿时,矿工们就会比较这种新的食品和前两次(或者少于两次,如果前面运送食品的次数不足两次)的食品,并且: • 如果这几次食品车都是同一类型的食品,则矿工们产出一个单位的煤。 • 如果这几次食品车中有两种不同类型的食品,则矿工们产出两个单位的煤。 • 如果这几次食品车中有三种不同类型的食品,则矿工们产出三个单位的煤。 预先已知食品车的类型及其被配送的顺序。通过确定哪车食品送到哪个煤矿可以影响产煤量。食品车不能被拆分,每个食品车必须被全部送到一个或另一个煤矿。两个煤矿也并不要求接收相同数量的食品车(事实上,也允许将所有食品车都送到一个煤矿)。 任务 给出食品车的类型及其被配送的顺序,要求你写一个程序,确定哪个食品车应被送到煤矿1,哪个食品车应被送到煤矿2,以使得两个煤矿的产煤量的总和最大。
 
定义f[i][a1][a2][b1][b2];a1,a2和b1,b2分别表示两矿坑的前两天的食物。
数组大小为4*4*4*4*i,于是要用滚动数组。
之后就是愉快的转移~
 
/**************************************************************
    Problem: 1806
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:348 ms
    Memory:1372 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define FOR(x,y) for(int x=y;x<=3;++x)
int f[2][4][4][4][4],n,now=1,la=0,x;
char a[100010];
 
int sorce(int x,int y,int z)
{
    if(x==y)
    {
        if(x==0) return 1;
        if(x==z)return 1;
        else return 2;
    }
    else
    {
        if(x==0) if(y==z) return 1;
                else return 2;
        if(x==z||y==z) return 2;
        else return 3;
    }
}
 
int main()
{
//  freopen("1.txt","r",stdin);
    scanf("%d%s",&n,&a);
    memset(f[la],-1,sizeof(f[la]));
    f[la][0][0][0][0]=0;
    for(int i=0;i<n;++i)
    {
        if(a[i]=='M') x=1;
        if(a[i]=='B') x=2;
        if(a[i]=='F') x=3;
        memset(f[now],-1,sizeof(f[now]));
        FOR(a1,0) FOR(a2,a1?1:0) FOR(b1,0) FOR(b2,b1?1:0)
        if(f[la][a1][a2][b1][b2]>=0)
        {
    //      cout<<a1<<" "<<a2<<" "<<b1<<" "<<b2<<" "<<endl;
            f[now][a2][x][b1][b2]=max(f[now][a2][x][b1][b2],f[la][a1][a2][b1][b2]+sorce(a1,a2,x));
            f[now][a1][a2][b2][x]=max(f[now][a1][a2][b2][x],f[la][a1][a2][b1][b2]+sorce(b1,b2,x));
        }
        now=now^1;
        la=la^1;
    }
    int ans=0;
    FOR(a1,0) FOR(a2,a1?1:0) FOR(b1,0) FOR(b2,b1?1:0)
        ans=max(ans,f[la][a1][a2][b1][b2]);
    printf("%d",ans);
    return 0;
}

 

Category: 未分类 | Tags:
7
27
2015
0

BZOJ 2748: [HAOI2012]音量调节

Description

一个吉他手准备参加一场演出。他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量。在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改变的音量是多少。每一次改变音量,他可以选择调高也可以调低。
音量用一个整数描述。输入文件中给定整数beginLevel,代表吉他刚开始的音量,以及整数maxLevel,代表吉他的最大音量。音量不能小于0也 不能大于maxLevel。输入文件中还给定了n个整数c1,c2,c3…..cn,表示在第i首歌开始之前吉他手想要改变的音量是多少。
吉他手想以最大的音量演奏最后一首歌,你的任务是找到这个最大音量是多少。

动态规划 定义bool型 f【第i首歌】【音量】 如果当前可以达到就用它更新下一首歌的状态。

/**************************************************************
    Problem: 2748
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1328 kb
****************************************************************/
 
#include<iostream>
#include<cstring>
#include<cstdio>
 
using namespace std;
 
int ma,n;
bool f[55][1010];
 
int main()
{
//  freopen("1.txt","r",stdin);
    int aa;
    scanf("%d%d%d",&n,&aa,&ma);
    f[0][aa]=1;
    for(int i=0;i<n;++i)
    {
        int c;
        scanf("%d",&c);
        for(int j=0;j<=ma;++j)
        { 
            if(f[i][j])
            {
                if(j+c<=ma) f[i+1][j+c]=1;
                if(j-c>=0) f[i+1][j-c]=1;
            }
        }
    }
    int a=-1;
    for(int j=0;j<=ma;++j)
    {
        if(f[n][j])
            a=j;
    }
    printf("%d",a);
    return 0;
         
}

Category: 未分类 | Tags:
7
27
2015
0

BZOJ 1208: [HNOI2004]宠物收养所

最近,阿Q开了一间宠物收养所。收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。每个领养者都希望领养到自己满意的宠物,阿Q根据领 养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠 物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太 少。 1. 被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为a,那么它将会领养一只目前未被领养的宠物中特点值最接近a的一只宠物。 (任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点 值分别为a-b和a+b,那么领养者将会领养特点值为a-b的那只宠物。 2. 收养宠物的人过多,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养 者,如果该宠物的特点值为a,存在两个领养者他们希望领养宠物的特点值分别为a-b和a+b,那么特点值为a-b的那个领养者将成功领养该宠物。 一个领养者领养了一个特点值为a的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为abs(a-b)。【任务描述】你得到了一年 当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。

 

刚看了SBT于是就用SBT写了,记录当前SBT中是人还是狗,每次判断相同的话就加入树中,不同找前驱和后驱,绝对值最小的删除点,更新答案。

前驱后驱写的时候凌乱了调了好久ORZ

/**************************************************************
    Problem: 1208
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:260 ms
    Memory:2528 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
 
using namespace std;
 
const int N=80010,mod=1000000;
 
struct T{
    int l,r,size,w;
}tr[N];
 
int n,now,lai,top;
int root;
long long ans=0;
void left_rot(int &x)
{
    int y=tr[x].r;
    tr[x].r=tr[y].l;
    tr[y].l=x;
    tr[y].size=tr[x].size;
    tr[x].size=tr[tr[x].l].size+tr[tr[x].r].size+1;
    x=y; 
}
void right_rot(int &x)
{
    int y=tr[x].l;
    tr[x].l=tr[y].r;
    tr[y].r=x;
    tr[y].size=tr[x].size;
    tr[x].size=tr[tr[x].l].size+tr[tr[x].r].size+1;
    x=y; 
}
void maintain(int &x,bool flag)
{
    if(!flag)
    {
        if(tr[tr[tr[x].l].l].size>tr[tr[x].r].size)
            right_rot(x);
        else if(tr[tr[tr[x].l].r].size>tr[tr[x].r].size)
        {
            left_rot(tr[x].l);
            right_rot(x);
        }
        else return ;
    }
    else
    {
        if(tr[tr[tr[x].r].r].size>tr[tr[x].l].size)
            left_rot(x);
        else if(tr[tr[tr[x].r].l].size>tr[tr[x].l].size)
        {
            right_rot(tr[x].r);
            left_rot(x);
        }
        else return ;
    }
    maintain(tr[x].l,0);
    maintain(tr[x].r,1);
    maintain(x,0);
    maintain(x,1);
}
void insert(int &x,int k)
{
    if(x==0)
    {
        x=++top;
        tr[x].l=tr[x].r=0;
        tr[x].size=1;
        tr[x].w=k;
    }
    else
    {
        tr[x].size++;
        if(k<tr[x].w)    insert(tr[x].l,k);
        else insert(tr[x].r,k);
        maintain(x,k>tr[x].w);
    }
}
int del(int &p,int w)
{
    tr[p].size--;
 
    if(w==tr[p].w||(tr[p].l==0&&w<tr[p].w)||tr[p].r==0&&w>tr[p].w)
    {
         
        int de=tr[p].w;
        if(!tr[p].l||!tr[p].r)
        {
            p=tr[p].l+tr[p].r;
        }
        else
        {
            tr[p].w=del(tr[p].l,w);
        }
    return de;
    }
    if(w<tr[p].w) return del(tr[p].l,w);
    else return del(tr[p].r,w);
}
int find_max(int &x,int y,int w)
{
    if(x==0) return y;
    if(tr[x].w>=w) return find_max(tr[x].l,x,w);
    else return find_max(tr[x].r,y,w);
}
int find_min(int &x,int y,int w)
{
    if(x==0) return y;
    if(tr[x].w<=w) return find_min(tr[x].r,x,w);
    else return find_min(tr[x].l,y,w);
}
 
int main()
{
//  freopen("1.txt","r",stdin);
//  freopen("2.out","w",stdout);
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(!lai)
        {
            now=a;
            insert(root,b);
            lai++;
        }
        else
        {
            if(now==a)
            {
                lai++;
                insert(root,b);
            }
            else
            {
                lai--;
                int x1=find_min(root,0,b),
                    x2=find_max(root,0,b),
                    p1=b-tr[x1].w,
                    p2=tr[x2].w-b;
                if(x2==0||(p1<=p2&&p1>=0&&x1!=0))
                {
                    ans+=p1;
                    ans%=mod;
                    del(root,tr[x1].w);
                }
                if(x1==0||(p1>p2&&p2>=0&&x2!=0))
                {
                    ans+=p2;
                    ans%=mod;
                    del(root,tr[x2].w);
                }
            }
        }
        //cout<<ans<<endl;
    }
    printf("%lld",ans);
    return 0;
}

Category: 未分类 | Tags:
7
24
2015
0

BZOJ 1503: [NOI2004]郁闷的出纳员

Description

OIER公司是一家大型专业化软件公司,有着数以万计的员 工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他 心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。 工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也 不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新 建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万 个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难 吧?

splay维护工资的顺序;

定义一个change变量,全体修改的操作就修改change,每次询问工资用splay的返回值加上change的值;

 

不要问我为啥会有个堆。。。。我是脑残

/**************************************************************
    Problem: 1503
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:868 ms
    Memory:5296 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
 
using namespace std;
 
int n,jx,change,leave=0; 
 
const int N=100010;
struct T{
    int lc,rc,fa,size,w;
}tr[N];
int tott,totd;
struct D{
    int pr,w;
}dui[N];
int root=0;
void up(int i)
{
    if(i==1) return ;
    if(dui[i].w<dui[i>>1].w)
    {
        swap(dui[i],dui[i>>1]);
        up(i>>1);
    }
}
void put(int pr,int w)
{
    dui[++totd].pr=pr;
    dui[totd].w=w;
    up(totd);
}
void down(int i)
{
    if(i<<1>totd) return ;
    int a=i<<1;
    if(a+1<=totd&&dui[a+1].w<dui[a].w)
        a++;
    if(dui[i].w>dui[a].w)
    {
        swap(dui[i],dui[a]);
        down(a);
    }
}
void pop()
{
    dui[1]=dui[totd--];
    down(1);
}
void setup(int i)
{
    if(!i) return ;
    tr[i].size=tr[tr[i].lc].size+tr[tr[i].rc].size+1;
}
 
void jia(int i,int k)
{
    if(k>tr[i].w)
    {
        if(tr[i].rc)
        {
            jia(tr[i].rc,k);
            setup(i);
        }
        else
        {
            tr[i].rc=++tott;
            tr[tott].fa=i;
            tr[tott].w=k;
            tr[tott].size=1;
            tr[tott].rc=0;
            tr[tott].lc=0;
            setup(i);
        }
    }
    else
    {
        if(tr[i].lc)
        {
            jia(tr[i].lc,k);
            setup(i);
        }
        else
        {
            tr[i].lc=++tott;
            tr[tott].fa=i;
            tr[tott].w=k;
            tr[tott].size=1;
            tr[tott].rc=0;
            tr[tott].lc=0;
            setup(i);
        }
    }
     
}
 
void xuan(int x)
{
     int y=tr[x].fa,z=tr[y].fa;
    if(x==tr[y].lc)
    {
        tr[y].lc=tr[x].rc;
        if(tr[y].lc)
            tr[tr[y].lc].fa=y;
        tr[x].fa=z;
        if(tr[z].lc==y) tr[z].lc=x;
        else tr[z].rc=x;
        tr[x].rc=y;
        tr[y].fa=x;
    }
    else
    {
        tr[y].rc=tr[x].lc;
        tr[tr[y].rc].fa=y;
        tr[x].fa=z;
        if(tr[z].lc==y) tr[z].lc=x;
        else tr[z].rc=x;
        tr[x].lc=y;
        tr[y].fa=x;
    }
    setup(y);
    setup(x);
}
void splay(int x,int p)
{
    int y,z;
    while(tr[x].fa!=p)
    {
        y=tr[x].fa;
        z=tr[y].fa;
        if(z==p)
        {
            xuan(x);
        }
        else
        {
            if(tr[y].lc==x)
            {
                if(tr[z].lc==y) xuan(y);
                else xuan(x);
                xuan(x);
            }
            else
            {
                if(tr[z].rc==y) xuan(y);
                else xuan(x);
                xuan(x);
            }
        }
    }
    if(p==0) root=x;
}
int findmin(int a)
{
    if(!tr[a].lc) return a;
    else return findmin(tr[a].lc);
}
int findmax(int a)
{
    if(!tr[a].rc) return a;
    else return findmax(tr[a].rc);
}
void shan(int i)
{
    splay(i,0);
    int a=findmax(tr[i].lc);
    int b=findmin(tr[i].rc);
    splay(a,0);
    splay(b,a);
    tr[b].lc=0;
    setup(b);
    setup(a);
}
 
int find(int i,int x)
{
    if(root==i)
        if(x>=tr[i].size) return -change-1;
    if(tr[tr[i].rc].size>=x&&tr[i].rc) return find(tr[i].rc,x);
    if(tr[tr[i].rc].size+1==x) return tr[i].w;
    if(tr[tr[i].rc].size+1<=x) return find(tr[i].lc,x-tr[tr[i].rc].size-1);
}
 
int main()
{
//  freopen("1.txt","r",stdin);
    scanf("%d%d",&n,&jx);
    char a1;
    int a2;
    jia(0,-100000000);
    jia(1,100000000);
    root=2;
    while(n--)
    {
    //  a1=getchar();
        scanf("%c",&a1);
        while(a1<41)
        scanf("%c",&a1);    
        scanf("%d",&a2);
        if(a1=='I'&&a2>=jx)
        {
            jia(root,a2-change);
            splay(tott,0);
            put(tott,a2-change);
        }
             
        if(a1=='A')
            change+=a2;
        if(a1=='S')
        {
            change-=a2;
            while(dui[1].w+change<jx&&totd)
            {
                shan(dui[1].pr);
                pop();
                leave++;
            }
        }
        if(a1=='F')
            printf("%d\n",find(root,a2+1)+change);
         
         
    }
     
    printf("%d",leave);
    return 0;
     
}

Category: 未分类 | Tags:
7
24
2015
0

BZOJ 1858: [Scoi2010]序列操作

Description

lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
 
坑爹的线段树。。
对于每个区间,维护:
左右连续串的长度,记录左右两边是0还是1;
记录区间内最长的连续的0,和1的数;
写起来太麻烦,调了一天ORZ;
 
/**************************************************************
    Problem: 1858
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:1696 ms
    Memory:22468 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
 
using namespace std;
 
 
const int N=100010;
int m,n;
struct tr{
    int lz,rz,l,r,sum,sum1,sum0;
    bool ll,rr,la[2],lqf;
}t[N*6];
bool AA[N];
void fg(int ,int ,int ,int );
void qf(int ,int ,int );
void build(int wz,int l,int r)
{
    t[wz].l=l;
    t[wz].r=r;
    if(l==r) 
    {
        t[wz].lz=1;
        t[wz].rz=1;
        t[wz].ll=AA[l];
        t[wz].rr=AA[l];
        t[wz].sum1=int(AA[l]);
        t[wz].sum=t[wz].sum1;
        t[wz].sum0=!t[wz].sum1;
        return ;
    }
     
    int mid=(r+l)/2;
    build(wz<<1,l,mid);
    build((wz<<1)+1,mid+1,r);
     
         
    t[wz].sum=t[wz*2].sum+t[wz*2+1].sum;
     
    if(t[wz*2].lz==mid-l+1)
    {
        t[wz].lz=mid-l+1;
        if(t[wz*2].ll==t[wz*2+1].ll)
        t[wz].lz+=t[wz*2+1].lz;
    }
    else
        t[wz].lz=t[wz*2].lz;
    t[wz].ll=t[wz*2].ll;
     
    if(t[wz*2+1].rz==r-mid)
    {
        t[wz].rz=r-mid;
        if(t[wz*2+1].rr==t[wz*2].rr)
        t[wz].rz+=t[wz*2].rz;
    }
    else
        t[wz].rz=t[wz*2+1].rz;
    t[wz].rr=t[wz*2+1].rr;
     
    t[wz].sum1=max(t[wz*2].sum1,t[wz*2+1].sum1);
    if(t[wz*2].rr&&t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum1)
        t[wz].sum1=t[wz*2].rz+t[wz*2+1].lz;
    t[wz].sum0=max(t[wz*2].sum0,t[wz*2+1].sum0);
    if(!t[wz*2].rr&&!t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum0)
        t[wz].sum0=t[wz*2].rz+t[wz*2+1].lz;
         
    return ;
}
 
 
void fg(int p,int wz,int l,int r)
{
    if(t[wz].l==0||t[wz].r==0) return ;
    if(t[wz].l>=l&&t[wz].r<=r)
    {
        t[wz].la[p]=1,t[wz].la[!p]=0,t[wz].lqf=0;
        t[wz].ll=p;
        t[wz].rr=p;
        t[wz].rz=(t[wz].r-t[wz].l+1);
        t[wz].lz=t[wz].rz;
        t[wz].sum1=p==1?t[wz].lz:0;
        t[wz].sum=t[wz].sum1;
        t[wz].sum0=t[wz].lz-t[wz].sum1;
    }
     
    else
    {
        if(t[wz].la[0])
            fg(0,wz*2,1,n),fg(0,wz*2+1,1,n);
             
        if(t[wz].la[1])
            fg(1,wz*2+1,1,n),fg(1,wz*2,1,n);
        if(t[wz].lqf)
            qf(wz*2,1,n),qf(wz*2+1,1,n);
             
        t[wz].lqf=0;
        t[wz].la[0]=0;
        t[wz].la[1]=0;
         
        if(t[wz*2].r>=l) fg(p,wz*2,l,r);
        if(t[wz*2+1].l<=r) fg(p,wz*2+1,l,r);
         
        t[wz].sum=t[wz*2].sum+t[wz*2+1].sum;
        int mid=(t[wz].l+t[wz].r)/2;
        if(t[wz*2].lz==mid-t[wz].l+1)
        {
        t[wz].lz=mid-t[wz].l+1;
        if(t[wz*2].ll==t[wz*2+1].ll)
        t[wz].lz+=t[wz*2+1].lz;
        }
        else
            t[wz].lz=t[wz*2].lz;
        t[wz].ll=t[wz*2].ll;
         
        if(t[wz*2+1].rz==t[wz].r-mid)
        {
            t[wz].rz=t[wz].r-mid;
            if(t[wz*2+1].rr==t[wz*2].rr)
            t[wz].rz+=t[wz*2].rz;
        }
        else
            t[wz].rz=t[wz*2+1].rz;
        t[wz].rr=t[wz*2+1].rr;
         
        t[wz].sum1=max(t[wz*2].sum1,t[wz*2+1].sum1);
        if(t[wz*2].rr&&t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum1)
            t[wz].sum1=t[wz*2].rz+t[wz*2+1].lz;
        t[wz].sum0=max(t[wz*2].sum0,t[wz*2+1].sum0);
        if(!t[wz*2].rr&&!t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum0)
            t[wz].sum0=t[wz*2].rz+t[wz*2+1].lz;
    }
}
 
void qf(int wz,int l,int r)
{
    if(t[wz].l==0||t[wz].r==0) return ;
    if(t[wz].l>=l&&t[wz].r<=r)
    {
        t[wz].ll=!t[wz].ll;
        t[wz].rr=!t[wz].rr;
        if(t[wz].la[0])
            t[wz].la[0]=0,t[wz].la[1]=1;
        else
        if(t[wz].la[1])
            t[wz].la[1]=0,t[wz].la[0]=1;
        if(!t[wz].la[0]&&!t[wz].la[1])
            t[wz].lqf=!t[wz].lqf;
         
        t[wz].sum=t[wz].r-t[wz].l+1-t[wz].sum;
        swap(t[wz].sum0,t[wz].sum1);
         
    }
    else
    {
        if(t[wz].la[0])
            fg(0,wz*2,1,n),fg(0,wz*2+1,1,n);
             
        if(t[wz].la[1])
            fg(1,wz*2+1,1,n),fg(1,wz*2,1,n);
        if(t[wz].lqf)
            qf(wz*2,1,n),qf(wz*2+1,1,n);
             
        t[wz].lqf=t[wz].la[0]=t[wz].la[1]=0;
         
        if(t[wz*2].r>=l) qf(wz*2,l,r);
        if(t[wz*2+1].l<=r) qf(wz*2+1,l,r);
         
        t[wz].sum=t[wz*2].sum+t[wz*2+1].sum;
        int mid=(t[wz].l+t[wz].r)/2;
        if(t[wz*2].lz==mid-t[wz].l+1)
        {
        t[wz].lz=mid-t[wz].l+1;
        if(t[wz*2].ll==t[wz*2+1].ll)
        t[wz].lz+=t[wz*2+1].lz;
        }
        else
            t[wz].lz=t[wz*2].lz;
        t[wz].ll=t[wz*2].ll;
         
        if(t[wz*2+1].rz==t[wz].r-mid)
        {
            t[wz].rz=t[wz].r-mid;
            if(t[wz*2+1].rr==t[wz*2].rr)
            t[wz].rz+=t[wz*2].rz;
        }
        else
            t[wz].rz=t[wz*2+1].rz;
        t[wz].rr=t[wz*2+1].rr;
         
        t[wz].sum1=max(t[wz*2].sum1,t[wz*2+1].sum1);
        if(t[wz*2].rr&&t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum1)
            t[wz].sum1=t[wz*2].rz+t[wz*2+1].lz;
        t[wz].sum0=max(t[wz*2].sum0,t[wz*2+1].sum0);
        if(!t[wz*2].rr&&!t[wz*2+1].ll&&t[wz*2].rz+t[wz*2+1].lz>t[wz].sum0)
            t[wz].sum0=t[wz*2].rz+t[wz*2+1].lz;
    }
}
int findsum(int wz,int l,int r)
{
    if(t[wz].la[0])
        fg(0,wz*2,1,n),fg(0,wz*2+1,1,n);
         
    if(t[wz].la[1])
        fg(1,wz*2+1,1,n),fg(1,wz*2,1,n);
    if(t[wz].lqf)
        qf(wz*2,1,n),qf(wz*2+1,1,n);
             
    t[wz].lqf=0;
    t[wz].la[0]=0;
    t[wz].la[1]=0;
     
    if(t[wz].l>=l&&t[wz].r<=r)
        return t[wz].sum;
    else
    {
        int ans=0;
        if(t[wz*2].r>=l) ans+=findsum(wz*2,l,r);
        if(t[wz*2+1].l<=r) ans+=findsum(wz*2+1,l,r);
        return ans;
    }
}
 
int findmax(int wz,int l,int r)
{
    if(t[wz].la[0])
        fg(0,wz*2,1,n),fg(0,wz*2+1,1,n);
    if(t[wz].la[1])
        fg(1,wz*2+1,1,n),fg(1,wz*2,1,n);
    if(t[wz].lqf)
        qf(wz*2,1,n),qf(wz*2+1,1,n);
             
    t[wz].lqf=0;
    t[wz].la[0]=0;
    t[wz].la[1]=0;
     
    if(t[wz].l>=l&&t[wz].r<=r)
        return t[wz].sum1;
    int ans=0;
    if(t[wz*2].r>=l) ans=max(ans,findmax(wz*2,l,r));
    if(t[wz*2+1].l<=r) ans=max(ans,findmax(wz*2+1,l,r));
    if(t[wz*2].r>=l&&t[wz*2+1].l<=r&&t[wz*2].rr&&t[wz*2+1].ll)
    {
        int lll=min(t[wz*2].rz,t[wz*2].r-l+1);
        int rrr=min(t[wz*2+1].lz,r-t[wz*2+1].l+1);
        ans=max(ans,rrr+lll);
    }
    return ans;
     
}
 
int main()
{
//freopen("1.txt","r",stdin);
//freopen("1.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        cin>>AA[i];
    build(1,1,n);
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        b++;
        c++;
        if(a<=1)
            fg(a,1,b,c);
         
        if(a==2)
            qf(1,b,c);
         
        if(a==3)
            printf("%d\n",findsum(1,b,c));
        if(a==4)
            printf("%d\n",findmax(1,b,c));
    }
    return 0;
     
}
Category: 未分类 | Tags:
7
21
2015
0

BZOJ 3172 单词

Description

某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

 

将每一个单词读入,每一个单词中间用一个没有出现并小于前面字符的字符。之后用后缀数组算出公共前缀的height数组。

对于每个单词,向前后搜索,若公共前缀大于单词长度,说明出现过一次;

用来分隔的字符需要是最小的,我开始用最大的套模版,结果死循环了。。。。ORZ。会出现sa【0】==0的情况,貌似会挂。

 

代码:

/**************************************************************
    Problem: 3172
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:1308 ms
    Memory:33496 kb
****************************************************************/
 
#include<iostream>
#include<cstdio> 
#include<cstring>
 
using namespace std;
 
const int N=1002001;
 
int r[N],rank[N],wa[N],wb[N],ws1[N],wv[N],h[N],sa[N];
 
int p[210],l[210],n;
 
bool cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
 
void da(int *r,int *sa,int n,int m)
{
    int *x=wa,*y=wb,*t;
    for(int i=0;i<m;++i) ws1[i]=0;
    for(int i=0;i<n;++i) ws1[x[i]=r[i]]++;
    for(int i=1;i<m;++i) ws1[i]+=ws1[i-1];
    for(int i=n-1;i>=0;i--) sa[--ws1[x[i]]]=i;
    for(int p1=1,j=1;p1<n;j*=2,m=p1)
    {
        p1=0;
        for(int i=n-j;i<n;i++) y[p1++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=j) y[p1++]=sa[i]-j;
        for(int i=0;i<n;i++) wv[i]=x[y[i]];
        for(int i=0;i<m;++i) ws1[i]=0;
        for(int i=0;i<n;++i) ws1[wv[i]]++;
        for(int i=1;i<m;++i) ws1[i]+=ws1[i-1];
        for(int i=n-1;i>=0;--i) sa[--ws1[wv[i]]]=y[i];
        t=x,x=y,y=t,p1=1,x[sa[0]]=0;
        for(int i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p1-1:p1++;
             
         
    }
}
void height(int *r,int *sa,int n)
{
    int i,j,k=0;
    for(i=1;i<n;++i) rank[sa[i]]=i;
    for(i=0;i<n;h[rank[i++]]=k)
        for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];++k);
}
 
int main()
{
    scanf("%d",&n);
    int tot=0;
    for(int a,i=1;i<=n;++i)
    {
        char s[N];
        scanf("%s",s);
        a=strlen(s);
        p[i]=tot;
        for(int j1=0;j1<a;++j1)
            r[j1+tot]=s[j1]-'a'+2;
        l[i]=a;
        tot+=a;
        r[tot++]=1;
         
    }
     
    da(r,sa,tot,30);
     
    height(r,sa,tot);
     
    for(int i=1;i<=n;++i)
    {
        int t=rank[p[i]],j,left,right;
        for(j=t;j&&h[j]>=l[i];j--);
        left=j;
        for(j=t+1;j<tot&&h[j]>=l[i];j++);
        right=j;
        printf("%d\n",right-left);
    } 
}
Category: 未分类 | Tags:
7
13
2015
0

BZOJ 1003 物流运输trans

Description

物 流公司要把一批货物从码头A运到码头B。由于货物量比较大,需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路 线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的 地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个n天的运输计划,使得总成本尽可能地小。

动规,f(i)=f(j)+c(i,j);

c表示从i天到j天的最小钱数。

跑了N方次SPFA真心不敢想啊ORZ

注意n和m不要弄混。。。(不要问我为啥这样说。。。)

/**************************************************************
    Problem: 1003
    User: 1115825064
    Language: C++
    Result: Accepted
    Time:40 ms
    Memory:1588 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
 
using namespace std;
 
struct D{
    int to,next,w;
}e[10001];
int head1[23],tot=0;
#define LINK(x) for(int i=head1[x];i;i=e[i].next)
void jia(int u,int v,int w)
{
    e[++tot].w=w,e[tot].to=v,e[tot].next=head1[u];head1[u]=tot;
}
int n,m,k,e1;
bool g[30][101];
int cost[101][101],que[40005],head,tail;
int f[102];
int main()
{
//  freopen("1.txt","r",stdin);
     
    scanf("%d%d%d%d",&n,&m,&k,&e1);
    for(int i=1;i<=e1;++i)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        jia(a,b,c);
        jia(b,a,c);
    }
    int d1;
    scanf("%d",&d1);
    while(d1--)
    {
        int a,b,c;
        scanf("%d%d%d",&c,&a,&b);
        if(a>b) swap(a,b);
        for(int j=a;j<=b;++j)
            {
                g[c][j]=1;
            }
    }
    bool d[30],g1[30];
    for(int i1=1;i1<=n;++i1)
    for(int j=i1;j<=n;++j)
    {
        memset(d,0,sizeof(d));
        memset(g1,0,sizeof(g1));
        for(int a1=1;a1<=m;++a1)
            for(int a2=i1;a2<=j;++a2)
            {
                if(g[a1][a2]) {
                    g1[a1]=1;
                    break;  
                }
            }
         
        for(int i=1;i<=m;++i)
        f[i]=100000000;
         
        f[1]=0;
        head=0;tail=1;
        que[1]=1;
        while(head!=tail)
        {
            head%=40000;
            head++;
            int x=que[head];
            d[x]=0;
            LINK(x) 
            if(f[e[i].to]>f[x]+e[i].w&&!g1[e[i].to])
            {
                f[e[i].to]=f[x]+e[i].w;
                if(d[e[i].to]==0)
                {
                    tail%=40000;
                    que[++tail]=e[i].to;
                    d[e[i].to]=1;
                }
            }
        }
        cost[i1][j]=f[m];
    }
    for(int i=1;i<=n;++i)
        f[i]=100000000;
    f[0]=0;
    for(int i=1;i<=n;++i)
        for(int j=0;j<i;++j)
        f[i]=min(f[i],f[j]+k+cost[j+1][i]*(cost[j+1][i]>=100000000?1:i-j));
    printf("%d",f[n]-k);
    return 0;
}
Category: 未分类 | Tags:
7
13
2015
3

BZOJ 1855 股票交易

Category: 未分类 | Tags:

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com