許可權題 NFLSoj 32 輻射 題解

2021-08-15 01:40:44 字數 3472 閱讀 5451

先吐槽一波這題實在是太難寫了。。。

考慮乙個輻射源對其他點的貢獻,就是若干個正方形疊加在一起。 如:

0 0 0 0 0 0 0

0 1 1 1 1 1 0

0 1 2 2 2 1 0

0 1 2 3 2 1 0

0 1 2 2 2 1 0

0 1 1 1 1 1 0

0 0 0 0 0 0 0

考慮每個正方形,乙個通用的思路就是差分:

0 0 0 0 0 0 0

0 1 0 0 0 0 -1

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 0 0 0 0 0 0

0 -1 0 0 0 0 1

然後疊加之後就是:

0 0 0 0 0 0 0

0 1 0 0 0 0 -1

0 0 1 0 0 -1 0

0 0 0 1 -1 0 0

0 0 0 -1 1 0 0

0 0 -1 0 0 1 0

0 -1 0 0 0 0 1

顯然對於乙個輻射源的貢獻我們可以用差分做成上面這樣的東西

然後再對這個圖做乙個差分,按主對角線和輔對角線分別差分

然後先求一次斜的字首和,再求一次正的二維字首和得到原矩陣,再求一次二維字首和用於算答案

要非常注意對邊界的處理,上邊界和左邊界

注意四捨五入盡量避免實數運算

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ll long long

#define lb long double

#define x first

#define y second

#define pair pair#define pb push_back

#define pf push_front

#define mp make_pair

#define lowbit(x) x & (-x)

using namespace std;

const int mod=1e9+7;

const ll linf=2e16;

const int inf=2e9;

const int magic=348;

const double eps=1e-10;

inline int getint()

if (ch=='-') f=false,res=0; else f=true,res=ch-'0';

while (isdigit(ch=getchar())) res=res*10+ch-'0';

return f?res:-res;

}int w,h,n,q;

ll a[3000048],sum[3000048];

ll pos[3000048],neg[3000048];

ll prew[3000048],preh[3000048];

ll prew_pos[3000048],preh_pos[3000048];

ll prew_neg[3000048],preh_neg[3000048];

inline int getind(int x,int y)

void update_corner(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,ll num)

else if (y1<=0)

else if (x1<=0)

else

int cnt=0;

if (1<=x2 && x2<=w && 1<=y2 && y2<=h)

else if (1<=y2 && y2<=h)

if (1<=x3 && x3<=w && 1<=y3 && y3<=h)

else if (1<=x3 && x3<=w)

if (cnt==2) a[getind(x4,y4)]+=num;

}void update_neg(int x1,int y1,int x2,int y2,ll num)

if (x2>w)

int xx1=x1,xx2=x2,yy1=y1,yy2=y2;

if (xx1<=0)

if (yy2<=0)

neg[getind(xx1,yy1)]-=num;

if (xx21) neg[getind(xx2+1,yy2-1)]+=num;

if (x1<=0)

else

}if (x1<=0)

if (y1<=0)

pos[getind(x1,y1)]+=num;

if (1<=x2 && x2<=w-1 && 1<=y2 && y2<=h-1) pos[getind(x2+1,y2+1)]-=num;

}int main ()

for (i=2;i<=w;i++)

for (j=2;j<=h;j++)

pos[getind(i,j)]+=pos[getind(i-1,j-1)];

for (i=2;i<=w;i++)

for (j=h-1;j>=1;j--)

neg[getind(i,j)]+=neg[getind(i-1,j+1)];

for (i=2;i<=h;i++)

for (i=2;i<=w;i++)

for (i=1;i<=h;i++) preh[i]+=preh_pos[i]+preh_neg[i];

for (i=1;i<=w;i++) prew[i]+=prew_pos[i]+prew_neg[i];

for (i=1;i<=w;i++)

for (j=1;j<=h;j++)

a[getind(i,j)]+=pos[getind(i,j)]+neg[getind(i,j)];

for (i=1;i<=w;i++)

for (j=1;j<=h;j++)

for (i=2;i<=w;i++)

for (j=1;j<=h;j++)

sum[getind(i,j)]+=sum[getind(i-1,j)];

for (i=1;i<=w;i++)

for (j=2;j<=h;j++)

sum[getind(i,j)]+=sum[getind(i,j-1)];

for (i=2;i<=w;i++)

for (j=1;j<=h;j++)

sum[getind(i,j)]+=sum[getind(i-1,j)];

q=getint();

while (q--)

return 0;

}

許可權題 NFLSoj 113 或負 題解

一眼網路流 考慮超級源點向第i個長者連流量為l i 的邊,每個長者拆成d天,向每一天連n sum i j sum i j 表示他當天必須用來準備批判會的時間 每個長者的每一天專門再拆乙個點管理長者的午休,連hl hr sum1 i j sum1 i j 表示他當天午休時間內必須用來準備批判會的時間 ...

東華oj 基礎題第32題

32 完數個數 問題描述 完數的定義 如果乙個大於1的正整數的所有真因子 不包括自己的那些因子 之和等於它的本身,則稱這個數是完數,比如6,28都是完數 6 1 2 3 28 1 2 4 7 14。本題的任務是判斷兩個正整數之間完數的個數。輸入說明 第一行是乙個正整數n,表示測試例項的個數,然後就是...

leetcode刷題 劍指offer 32題

從上到下列印出二叉樹的每個節點,同一層的節點按照從左到右的順序列印。例如 給定二叉樹 3,9,20,null,null,15,7 3 9 20 15 7返回 3,9,20,15,7 新手上路,才學疏淺,望斧正 利用乙個佇列實現 class solution queue.add root while ...