1. 程式人生 > >洛谷P2119 魔法陣

洛谷P2119 魔法陣

%d 次數 單位 並且 最小 += b- printf mes

題目描述

六十年一次的魔法戰爭就要開始了,大魔法師準備從附近的魔法場中汲取魔法能量。

大魔法師有m個魔法物品,編號分別為1,2,...,m。每個物品具有一個魔法值,我們用Xi表示編號為i的物品的魔法值。每個魔法值Xi是不超過n的正整數,可能有多個物品的魔法值相同。

大魔法師認為,當且僅當四個編號為a,b,c,d的魔法物品滿足xa<xb<xc<xd,Xb-Xa=2(Xd-Xc),並且xb-xa<(xc-xb)/3時,這四個魔法物品形成了一個魔法陣,他稱這四個魔法物品分別為這個魔法陣的A物品,B物品,C物品,D物品。

現在,大魔法師想要知道,對於每個魔法物品,作為某個魔法陣的A物品出現的次數,作為B物品的次數,作為C物品的次數,和作為D物品的次數。

輸入輸出格式

輸入格式:

輸入文件的第一行包含兩個空格隔開的正整數n和m。

接下來m行,每行一個正整數,第i+1行的正整數表示Xi,即編號為i的物品的魔法值。

保證1 \le n \le 150001n15000,1 \le m \le 400001m40000,1 \le Xi \le n1Xin。每個Xi是分別在合法範圍內等概率隨機生成的。

輸出格式:

共輸出m行,每行四個整數。第i行的四個整數依次表示編號為i的物品作 為A,B,C,D物品分別出現的次數。

保證標準輸出中的每個數都不會超過10^9。

每行相鄰的兩個數之間用恰好一個空格隔開。

輸入輸出樣例

輸入樣例#1:
30 8
1
24
7
28
5
29
26
24
輸出樣例#1:
4 0 0 0
0 0 1 0
0 2 0 0
0 0 1 1
1 3 0 0
0 0 0 2
0 0 2 2
0 0 1 0
輸入樣例#2:
15 15
1 
2 
3 
4 
5
6 
7 
8 
9
10
11
12
13
14
15
輸出樣例#2:
5 0 0 0
4 0 0 0
3 5 0 0
2 4 0 0
1 3 0 0
0 2 0 0
0 1 0 0
0 0 0 0
0 0 0 0
0 0 1 0
0 0 2 1
0 0 3 2
0 0 4 3
0 0 5 4
0 0 0 5

說明

【樣例解釋1】

共有5個魔法陣,分別為:

物品1,3,7,6,其魔法值分別為1,7,26,29;

物品1,5,2,7,其魔法值分別為1,5,24,26;

物品1,5,7,4,其魔法值分別為1,5,26,28;

物品1,5,8,7,其魔法值分別為1,5,24,26;

物品5,3,4,6,其魔法值分別為5,7,28,29。

以物品5為例,它作為A物品出現了1次,作為B物品出現了3次,沒有作為C物品或者D物品出現,所以這一行輸出的四個數依次為1,3,0,0。

此外,如果我們將輸出看作一個m行4列的矩陣,那麽每一列上的m個數之和都應等於魔法陣的總數。所以,如果你的輸出不滿足這個性質,那麽這個輸出一定不正確。你可以通過這個性質在一定程度上檢查你的輸出的正確性。

【數據規模】

技術分享

分析:這道題有點喪病。首先方向要明確,我們肯定是要用n來做題,而不是用m,降低了復雜度.題目給了這麽多式子,我們要化簡一下題目給的這麽多式子,可以得到:

b-a=2(d-c),c-b>3(b-a),c-b>6(d-c).這樣d-c是最小單位,我們枚舉d-c的長度,然後枚舉d點的坐標,就能求出其他4個點的坐標,下面的更新過程有點棘手.

我們先用AB更新CD,如果知道了AB的組數i,又知道了D位置上的個數j,那麽C上的數就會出現i*j次,同理,利用C來更新D.接下來的一步就是利用CD更新AB.因為AB的位置我們假設是固定的,有可能會對多組CD有貢獻,我們要在處理的時候累加.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int n,m,num[40010],a[15010],b[15010],c[15010],d[15010],t[40010];

int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= m; i++)
    {
        scanf("%d",&t[i]);
        num[t[i]]++;
    }
    for (int i = 1; i <= n / 9; i++) //AB --> CD
    {
        int sum = 0,x = i * 9 + 1;
        for (int j = x + 1; j <= n; j++)
        {
            sum += num[j - x]*num[j - x + 2 * i];
            d[j] += sum * num[j - i];
            c[j - i] += sum * num[j];
        }
        sum = 0;
        x = 8 * i + 1;
        for (int j = n - 9 * i - 1; j >= 1; j--) //CD --> AB
        {
           sum += num[j + x] * num[j + x + i];
           a[j] += sum * num[j + i * 2];
           b[j + i * 2] += sum * num[j];
        }
    }
    for (int i = 1; i <= m; i++)
    printf("%d %d %d %d\n",a[t[i]],b[t[i]],c[t[i]],d[t[i]]);
    
    return 0;
}

洛谷P2119 魔法陣