先吐槽一波這題實在是太難寫了。。。
考慮乙個輻射源對其他點的貢獻,就是若干個正方形疊加在一起。 如:
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 ...