zoukankan      html  css  js  c++  java
  • 2018ICPC 焦作 训练赛

    赛后总结:

    先把所有的可做题放上线程,debug在线程上有题的时候永远下机找

    宁愿机下多线程debug不要机下多线程空想题

    A. 0:05:54 solved by hl

    温暖的签到

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second
    typedef vector<int> VI;
    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 * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 110;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    int N,M,K;
    int main(){
        int T = read();
        while(T--){
            int ans = 0;
            for(int i = 1; i <= 4 ; i ++) ans += (read() != 0);
            if(ans == 0) puts("Typically Otaku");
            else if(ans == 1) puts("Eye-opener");
            else if(ans == 2) puts("Young Traveller");
            else if(ans == 3) puts("Excellent Traveller");
            else puts("Contemporary Xu Xiake");
        }
        return 0;
    }
    A

    B.3:57:18 solved by gbs

    思维题
    要打倒两个敌人,那么必然先打倒一个,后打倒另一个
    设打倒第一个敌人 hp为hp_1 打倒其需要花费回合turn_1 第二个则是hp_2 turn_2 ,设turn_sum = turn_1 + turn_2
    设F(x) = (1+x)*x/2; 可以理解为前x回合造成的总伤害(包括溢出伤害)
    那么一定有F(turn_1)>=hp_1 F(turn_sum)>=hp_1 + hp_2 否则总伤害不够

    有一条性质
    计数列 1,2,3……n 的和为sum 那么对于任意的1<=k <=sum 那么一定存在一种取法,从数列中取出若干数,使和为k(一种取法:从n到1枚举,若可以取便取。直到和等于k)
    类似的,在攻击第一个敌人时,可以取出若干次攻击来攻击第二个敌人,那么不会有伤害溢出。
    由此容易推断出满足F(turn_1)>=hp_1 和F(turn_sum)>=hp_1 + hp_2 的最小 turn_1 和turn_sum即是最优解,可以用二分来查找

    分先攻A 和先攻B两种情况讨论,就可以得到受到的伤害最小(存在turn_1 = turn_sum的情况,但这种情况不处理貌似对解题也没有影响)

    麻烦的是要输出字典序最小的攻击方案,这里分先攻A和先攻B两种情况

    首先要计算如果前turn_1轮全打第一个敌人的溢出伤害 over_damage1 打完两个敌人最多溢出的伤害为over_damage2
    可以知道over_damage1 <turn_1 否则可以提前一轮打败第一个敌人

    假设在前turn_1轮 期间对第二个敌人造成了 k1点伤害
    那么k1>=over_damage1-over_damage2 否则打败后一个敌人的时间要延后一轮 不是最优解
    那么有 over_damage1-over_damage2 <=k1 <=over_damage1

    如果先攻A
    若over_damage1-over_damage2<=0则 前turn_1轮全攻A 后面的轮全攻B
    如果over_damage1-over_damage2>0,那么在前turn_1轮必须对B造成伤害 索性造成over_damage1的伤害,那么只要再第 over_damage1 轮攻击一次B即可,前面已经证明了over_damage1 <turn_1
    此时B出现最靠后,字典序最小

    如果先攻B
    在前turn_1次攻击中 选择若干次攻击A
    此时同样有over_damage1-over_damage2 <=k1 <=over_damage1
    此时还要用到上的的函数F(x) = (1+x)*x/2
    找到最大的t 使得F(t) >=over_damage1 ,如果不考虑over_damage1-over_damage2 <=k1这个条件
    那么答案必然是若干个A+若干个B+若干个A的形式 例如如AAABBBBAAAAA (否则,如果出现A在两个B之间,则可以把这个A左移,使得字典序变小)
    考虑到over_damage1-over_damage2 <=k1这个条件 在构造后如果不满足这个条件 ,那么把前面若干个连续的A最后一个A的位置右移即可

    如果先攻A和先攻B,受到的总伤害相同,那么对于这两种情况都计算一下,然后比较字符串的大小

    #include <iostream>
    #include<stack>
    #include<math.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<ctime>
    #include<complex>
    #include<stdio.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const int mod =1e9+7;
    int hpa,hpb,atka,atkb;
    int hpab;
    int sum_turn;
    int a_turn;
    int a_re;
    int b_turn;
    int b_re;
    LL ap_damage;
    LL bp_damage;
    int sum_r;
    int give_up,give_down;
    int theover(int a)
    {
        int left1 = 0;
        int right1 = 70000;
    
        LL ans;
        while(right1 -left1>1)
        {
            int mid = (left1 +right1)/2;
            ans =1LL *mid*(mid+1)/2;
            if (ans >=a)
                right1 =mid;
            else
                left1 = mid;
        }
        return right1;
    }
    int theblow(int a)
    {
        int left1 = 0;
        int right1 = 70000;
        int mid;
        LL ans;
        while(right1 -left1>1)
        {
            int mid = (left1 +right1)/2;
            ans =1LL *mid*(mid+1)/2;
            if (ans <=a)
                left1 =mid;
            else
                right1 = mid;
        }
        return left1;
    }
    char ansa[100005];
    char ansb[100005];
    bool cmp1()
    {
        for (int i=0; i<sum_turn; i++)
        {
            if (ansa[i] < ansb[i])
                return true;
            if (ansa[i] > ansb[i])
                return false;
        }
        return true;
    }
    int main()
    {
        int t;
        cin >>t;
        while(t--)
        {
            scanf("%d%d%d%d",&hpa,&hpb,&atka,&atkb);
            hpab = hpa+hpb;
            sum_turn = theover(hpab);
            sum_r = 1LL * (sum_turn+1)*sum_turn/2 - hpab;
    
            a_turn = theover(hpa);
            a_re = 1LL *(a_turn +1)*a_turn /2-hpa;
    
            b_turn = theover(hpb);
            b_re = 1LL *(b_turn +1)*b_turn /2-hpb;
    
            ap_damage = 1LL*atka * a_turn + 1LL*sum_turn * atkb;
            bp_damage = 1LL*atkb * b_turn + 1LL*sum_turn * atka;
            bool if_a_first= false;
            bool if_b_c = false;
            if (a_turn == sum_turn)
                if_a_first = false;
            else if (b_turn == sum_turn)
                if_a_first = true;
            else if (ap_damage <= bp_damage)
            {
                if_a_first = true;
                if (ap_damage == bp_damage)
                {
                    if_b_c = true;
                }
            }
            else
                if_a_first = false;
            LL fin_ans;
            if (if_a_first)//A first
            {
                fin_ans = ap_damage;
                give_up = a_re;
                give_down = a_re - sum_r;
                for (int i=0; i<a_turn; i++)
                    ansa[i] ='A';
                for (int i=a_turn; i<sum_turn; i++)
                {
                    ansa[i] ='B';
                }
                ansa[sum_turn] = 0;
    
    
                if (give_down>0)
                {
                    ansa[give_up-1]='B';
                }
            }
            if (if_b_c || !if_a_first)
            {
                fin_ans = bp_damage;
                give_up = b_re;
                give_down = b_re - sum_r;
                for (int i=0; i<b_turn; i++)
                    ansb[i] ='B';
                for (int i=b_turn; i<sum_turn; i++)
                {
                    ansb[i] ='A';
                }
                ansb[sum_turn] = 0;
    
    
                int dt1 = theblow(b_re);
                for (int i =0; i<dt1; i++)
                    ansb[i] ='A';
                int now_have = dt1 * (dt1+1)/2;
                if (now_have <give_down)
                {
                    now_have = give_down -now_have;
                    ansb[dt1-1]='B';
                    ansb[dt1-1+now_have]='A';
                }
    
            }
            cout<<fin_ans<<' ';
            if (if_b_c)
            {
                if(cmp1())
                    printf("%s
    ",ansa);
                else
                    printf("%s
    ",ansb);
            }
            else if(if_a_first)
                printf("%s
    ",ansa);
            else
                printf("%s
    ",ansb);
        }
    
    
        return 0;
    }
    
    
    /*
    111
    5111111 11111116 12133215 251111111
    111
    5 15 5 25
    5 14 5 25
    5 13 5 25
    5 12 5 25
    3
    14 14 5 5
    14 14 5 5
    */
    B

    C.3:01:00(-1) solved by zcz

    用四个变量维护当前棋子的最左边,最右边,最上边,最下边

    由八皇后棋子摆法的特性可知 只有同时存在于最左(右)和最上(下)的棋子才有可能重叠。

    与此同时用两个变量表示棋盘的移动代替棋子的移动

    当询问!的时候,判断每两个边界重合部分有多少点

    当询问?的时候,如果点在边界上,则横纵坐标和边界相同,否则往棋盘相反的方向移动(不在边界上表示还未接触过棋盘的边界,因此每次移动都是K步不存在碰撞)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct Point
    {
        int x,y,flag;
    };
    
    Point p[300005];
    int n,m;
    int C[5];
    
    int a[300005],b[300005];
    int L,R,U,D,l,r,u,d,tl,tr,tu,td,DX,DY;
    int yin[10];
    long long C2(long long a)
    {
        return a*(a-1)/2;
    }
    
    
    int main()
    {
        yin[3]=1;
        yin[8]=2;
        yin[4]=3;
        yin[6]=4;
        int T;
        cin>>T;
        while(T--)
        {
            cin>>n>>m;
            for(int i=0;i<=4;i++)   C[i]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&p[i].x,&p[i].y);
                int t=p[i].x;
                p[i].x=p[i].y;
                p[i].y=n-t+1;
                p[i].flag=0;
                if(p[i].x==n)
                {
                    p[i].flag=1;
                }
                else if(p[i].x==1)
                {
                    p[i].flag=2;
                }
                if(p[i].y==1)
                {
                    C[yin[p[i].flag]*3]++;
                    p[i].flag=3;
                }
                else if(p[i].y==n)
                {
                    C[yin[p[i].flag*4]]++;
                    p[i].flag=4;
                }
                a[p[i].x]=i;
                b[p[i].y]=i;
            }
            l=L=tl=1;
            r=R=tr=n;
            d=D=td=1;
            u=U=tu=n;
            DX=DY=0;
            char s[2];
            int k;
            int flag1=0,flag2=0;
            while(m--)
            {
                scanf("%s",s);
                if(s[0]=='D')
                {
                    scanf("%d",&k);
                    DY-=k;
                    tu-=k;
                    td-=k;
                    tu=max(tu,1);
                    td=max(td,1);
                    if(D+k<=n)
                    {
                        D+=k;
                        U+=k;
                    }
                    else
                    {
                        D=n;
                        U=2*n-1;
                    }
                    if(flag1)   continue;
                    if(D>=u)
                    {
                        flag1=1;
                        continue;
                    }
                    if(D>d)
                    {
                        for(int i=d+1;i<=D;i++)
                        {
                            int j=b[i];
                            C[yin[p[j].flag*3]]++;
                            p[j].flag=3;
                        }
                        d=D;
                    }
                }
                else if(s[0]=='U')
                {
                    scanf("%d",&k);
                    DY+=k;
                    tu+=k;
                    td+=k;
                    tu=min(tu,n);
                    td=min(td,n);
                    if(U-k>=1)
                    {
                        U-=k;
                        D-=k;
                    }
                    else
                    {
                        U=1;
                        D=2-n;
                    }
                    if(flag1)   continue;
                    if(U<=d)
                    {
                        flag1=1;
                        continue;
                    }
                    if(U<u)
                    {
                        for(int i=u-1;i>=U;i--)
                        {
                            int j=b[i];
                            C[yin[p[j].flag*4]]++;
                            p[j].flag=4;
                        }
                        u=U;
                    }
                }
                else if(s[0]=='R')
                {
                    scanf("%d",&k);
                    DX+=k;
                    tl+=k;
                    tr+=k;
                    tl=min(tl,n);
                    tr=min(tr,n);
                    if(R-k>=1)
                    {
                        R-=k;
                        L-=k;
                    }
                    else
                    {
                        R=1;
                        L=2-n;
                    }
                    if(flag2)      continue;
                    if(R<=l)
                    {
                        flag2=1;
                        continue;
                    }
                    if(R<r)
                    {
                        for(int i=r-1;i>=R;i--)
                        {
                            int j=a[i];
                            C[yin[p[j].flag*1]]++;
                            p[j].flag=1;
                        }
                        r=R;
                    }
                }
                else if(s[0]=='L')
                {
                    scanf("%d",&k);
                    DX-=k;
                    tl-=k;
                    tr-=k;
                    tl=max(tl,1);
                    tr=max(tr,1);
                    if(L+k<=n)
                    {
                        L+=k;
                        R+=k;
                    }
                    else
                    {
                        L=n;
                        R=2*n-1;
                    }
                    if(flag2)   continue;
                    if(L>=r)
                    {
                        flag2=1;
                        continue;
                    }
                    if(L>l)
                    {
                        for(int i=l+1;i<=L;i++)
                        {
                            int j=a[i];
                            C[yin[p[j].flag*2]]++;
                            p[j].flag=2;
                        }
                        l=L;
                    }
                }
                else if(s[0]=='!')
                {
                    long long ans=0;
                    if(flag1&&flag2)
                    {
                        ans=C2(n);
                    }
                    else if(flag1)
                    {
                        ans=C2(l)+C2(n-r+1);
                    }
                    else if(flag2)
                    {
                        ans=C2(d)+C2(n-u+1);
                    }
                    else
                    {
                        ans=C2(C[1])+C2(C[2])+C2(C[3])+C2(C[4]);
                    }
                    printf("%lld
    ",ans);
                }
                else if(s[0]=='?')
                {
                    scanf("%d",&k);
                    int ans1,ans2;
                    if(p[k].x<=l||flag2)
                    {
                        ans1=tl;
                    }
                    else if(p[k].x>=r)
                    {
                        ans1=tr;
                    }
                    else
                    {
                        ans1=p[k].x+DX;
                    }
                    if(p[k].y<=d||flag1)
                    {
                        ans2=td;
                    }
                    else if(p[k].y>=u)
                    {
                        ans2=tu;
                    }
                    else
                    {
                        ans2=p[k].y+DY;
                    }
                    int t=ans2;
                    ans2=ans1;
                    ans1=n-t+1;
                    printf("%d %d
    ",ans1,ans2);
                }
            }
        }
    
        return 0;
    }
    C

    D.0:57:28(-1) solved by zcz

    手推一下公式

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    double pi=3.14159265358979323;
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            double a,b,r,d;
            cin>>a>>b>>r>>d;
            double l=sqrt((a+r)*(a+r)+b*b);
            double ar=asin(b/l);
            d=d/180*pi;
            double ans;
            if(d>ar)
            {
                ans=l-r;
            }
            else
            {
                ans=l*cos(ar-d)-r;
            }
                printf("%.10lf
    ",ans);
        }
    
        return 0;
    }
    D

    E.1:33:17 solved by gbs

    容易想到要找到的数是前k个素数的乘积,且这个乘积<=n
    根据样例可以找到规律,每多乘上一个素数p,答案乘上p/(p+1)
    然后使用大数模板或者java,再gcd即可

    对于每多乘上一个素数p,答案就乘上p/(p+1)的简略证明:
    每多乘上一个素数p 并联的电阻的个数就变为原来的两倍 这些新的电阻的倒数是原来对应电阻倒数的1/p
    那么所有电阻倒数和为原来倒数和的(1+p)/p 倒回来后为原来的p/(p+1)

    #include <iostream>
    #include<stack>
    #include<math.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<ctime>
    #include<complex>
    #include<stdio.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    using namespace std;
    typedef unsigned long long LL;
    const int mod =1e9+7;
    
    const int maxn = 1e3+15;
    bool vis[maxn+15];
    int prel[maxn/2+5];
    int time1[maxn/2+5];
    int pnum = 0;
    char an[105];
    int bn[105];
    int len1 ;
    void pre()
    {
        memset(vis,false,sizeof(vis));
        for (int i=2; i<maxn; i++)
        {
            if (!vis[i])
            {
                //cout<<i<<endl;
                prel[pnum++] = i;
                for (int j =i<<1; j<maxn; j+=i)
                {
                    vis[j] = true;
                }
            }
        }
    }
    LL gcd(LL a,LL b)
    {
        if (b == 0)
            return a;
        return gcd(b,a%b);
    }
    void fen(LL n,int tp1)
    {
        for (int i =0; i<pnum; i++)
        {
            if (n==1)
                return ;
            while(n%prel[i] ==0)
            {
                n/=prel[i];
                time1[i]+=tp1;
            }
        }
    }
    
    class bigint
    {
    public:
        int bnum;
        int an[105];
        bigint(int a = 0)
        {
            memset(an,0,sizeof(an));
            bnum = 1;
            an[0] = 0;
            if (a!= 0)
            {
                bnum = 0;
            }
            while(a)
            {
                an[bnum] = a%10;
                a/=10;
                bnum++;
            }
        }
        void mul(int a)
        {
            int jinwei = 0;
            for (int i=0; i<bnum; i++)
            {
                an[i] = an[i]*a+jinwei;
                //123112312
                jinwei = an[i]/10;
                an[i] =an[i]%10;
                if (jinwei >0)
                    bnum = max(i+2,bnum);
            }
        }
        void out()
        {
            for (int i=bnum-1; i>=0; i--)
            {
                printf("%d",an[i]);
            }
        }
    };
    
    
    bool op1(int pcd)
    {
        int tuiwei = 0;
        bool if_ok = false;;
        //cout<<"@"<<pcd<<endl;
        for (int i=len1-1; i>=0; i--)
        {
            bn[i] += tuiwei*10;
            tuiwei = bn[i]%pcd;
            bn[i] = bn[i]/pcd;
            //cout<<bn[i];
            if (bn[i]>0)
                if_ok = true;
        }//cout<<endl;
        return if_ok;
    
    }
    int main()
    {
        pre();
    
        int t;
        cin >>t;
        while(t--)
        {
            scanf("%s",an);
            len1 = strlen(an);
            for (int i=0; i<len1; i++)
            {
                bn[i] = an[len1-1-i]-'0';
                //cout<<bn[i]<<endl;
            }
    
            memset(time1,0,sizeof(time1));
            for (int i=0; i<pnum; i++)
            {
                //cout<<"ce"<<endl;
                if (op1(prel[i]))
                {
                    //cout<<"we"<<i<<endl;
                    fen(prel[i],1);
                    fen(prel[i]+1,-1);
                }
                else
                {
                    break;
                }
            }
            bigint fenzi(1),fenmu(1);
            for (int i=0; i<pnum; i++)
            {
                while(time1[i]>0)
                {
                    fenzi.mul(prel[i]);
                    --time1[i];
                }
                while(time1[i]<0)
                {
                    fenmu.mul(prel[i]);
                    ++time1[i];
                }
            }
            fenzi.out();
            cout<<"/";
            fenmu.out();
            cout<<endl;
        }
    
    
    
    
        return 0;
    }
    E

    F.3:37:54(-3) solved by hl

    WA原因:1.上下蜂巢可能会出现-- 或者 --这样的通路 2.编号标多了RE

    建完图就是一个裸BFS,建图比较麻烦,建议分奇数行和偶数行,用每个六边形的中点标识整个六边形,

    奇数行中点是(x,5) (x,17) (x,29) .....

    偶数行中点是(x,11) (x,23) (x,35)......

    然后每个六边形与其他六边形的边就是两个六边形中点连线的中点,判一下是不是空格就可以了,注意上下因为是---,有一个空格就算联通,需要特判

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second
    typedef vector<int> VI;
    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 * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 3e6 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    int N,M,K;
    const int a[6][2] = {-1,-3,-1,3,1,-3,1,3,-2,0,2,0};
    map<PII,int>P;
    PII id[maxn];
    LL dp[maxn];
    char MAP[7010][7010];
    int cnt,S,T;
    int main(){
        int q; Sca(q);
        while(q--){
            int x,y; P.clear();
            Sca2(x,y); cnt = 0;
            y = 6 * y + 3; x = 4 * x + 3;
            for(int i = 3; i < x ; i += 4){
                for(int j = 5; j <= y; j += 12){
                    P[mp(i,j)] = ++cnt;
                    id[cnt] = mp(i,j);
                }
            }
            for(int i = 5; i < x; i += 4){
                for(int j = 11; j <= y ; j += 12){
                    P[mp(i,j)] = ++cnt;
                    id[cnt] = mp(i,j);
                }
            }
            getchar();
            for(int i = 1; i <= x; i ++){
                gets(MAP[i] + 1);
            }
            for(int i = 1; i <= x; i ++){
                for(int j = 1; j <= y; j ++){
                    if(MAP[i][j] == 'S') S = P[mp(i,j)];
                    else if(MAP[i][j] == 'T') T = P[mp(i,j)];
                }
            }
            for(int i = 1; i <= cnt; i ++){
                int X = id[i].fi,Y = id[i].se;
                if(MAP[X - 2][Y - 1] == ' ' || MAP[X - 2][Y] == ' ' || MAP[X - 2][Y + 1] == ' '){
                    MAP[X - 2][Y - 1] = MAP[X - 2][Y] = MAP[X - 2][Y + 1] = ' ';
                }
                if(MAP[X + 2][Y - 1] == ' ' || MAP[X + 2][Y] == ' ' || MAP[X + 2][Y + 1] == ' '){
                    MAP[X + 2][Y - 1] = MAP[X + 2][Y] = MAP[X + 2][Y + 1] = ' ';
                }
            }
            for(int i = 0; i <= cnt; i ++) dp[i] = INF;
            queue<int>Q; while(!Q.empty()) Q.pop();
            Q.push(S); dp[S] = 1;
            while(!Q.empty() && dp[T] == INF){
                int u = Q.front(); Q.pop();
                int X = id[u].fi,Y = id[u].se;
                for(int i = 0 ; i < 6; i ++){
                    if(P[mp(X + a[i][0] * 2,Y + a[i][1] * 2)] && MAP[X + a[i][0]][Y + a[i][1]] == ' '){
                        int v = P[mp(X + a[i][0] * 2,Y + a[i][1] * 2)];
                        if(dp[v] > dp[u] + 1){
                            dp[v] = dp[u] + 1;
                            Q.push(v);
                        }
                    }
                }
            }
            if(dp[T] == INF) dp[T] = -1;
            Prl(dp[T]);
        }
        return 0;
    }
    F

    I.0:25:19 solved by hl

    策略画画就会发现是最左端取一个,最右端取一个,最左端取一个,最右端取一个......

    pre表示当前左端取的数的下标和,cnt1表示左端取了多少数字

    erp表示当前右边取的数的下表和,cnt2表示右端取了多少数字

    一个数a[l]加入的贡献就是ans += a[l] * cnt1 - pre + (erp - a[l] * cnt2);

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <bitset>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x)
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x)
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second
    typedef vector<int> VI;
    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 * 10 + c - '0';c = getchar();}return x*f;}
    const double PI = acos(-1.0);
    const double eps = 1e-9;
    const int maxn = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    int N,M,K;
    LL pre,erp,a[maxn];
    int main(){
        int T = read();
        while(T--){
            Sca(N);
            a[1] = 0;
            for(int i = 2; i <= N; i ++){
                Scl(a[i]); a[i] += a[i - 1];
            }
            LL ans = 0;
            int cnt = 1;
            int cnt1 = 0,cnt2 = 0;
            pre = erp = 0;
            int l = 1,r = N;
            for(int i = 1; i <= N ; i ++){
                if(cnt){
                    ans += a[l] * cnt1 - pre + (erp - a[l] * cnt2);
                    pre += a[l];
                    cnt1++; l++;
                }else{
                    ans += a[r] * cnt1 - pre + (erp - a[r] * cnt2);
                    erp += a[r];
                    cnt2++; r--;
                }
                cnt ^= 1;
                printf("%lld",ans);
                if(i != N) printf(" ");
            }
            puts("");
        }
        return 0;
    }
    I

    H.unsolved by hl

    应该是后缀数组加上某不知名数据结构去维护子区间的答案

    某数据结构没有顶住

  • 相关阅读:
    redis总结
    java程序启动脚本
    mysql生成百万测试数据脚本
    java分布式锁的实现及在springboot中的应用
    mysql使用总结
    一个java实现代码(服务)编排的思路(未完)
    sentinel自定义统一限流降级处理
    shell学习
    oracle查看被锁的事务进程sql
    Sql查询两个时间段有重叠的记录
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/11310811.html
Copyright © 2011-2022 走看看