SHOI2013 扇形面積並

2022-03-03 16:13:17 字數 1638 閱讀 6708

補一張圖

我們嘗試把圓上的扇形轉化成直線上的矩形——我們維護[1,2m]的區間,那麼每個能產生貢獻的子區間的長度第k大的半徑的平方的總和就是answer了。

怎麼轉化呢?左端點為a1+m+1,右端點為a2+m。為什麼要+m?因為原先的範圍是[-m,m]的,所以整體右移。為什麼左端點要+1?因為我們維護的是區間,所以這裡的每乙個下標表示的是以該position為右端點,長度為1的區間。

我們先按照半徑長度從大到小排序,如果乙個區間覆蓋數量超過k個,就不需要再處理了。(優化時間複雜度)

之後就是線段樹操作了。我們在更改的同時求出答案。(其實分開寫也行,就是要注意因為我們乘上的係數使然,所以區間必須也是當前的修改區間)

minn表示該區間的所有子區間覆蓋量的min,maxx是該區間的所有子區間的覆蓋量的max。

注意我們的siz是由左右子區間合併而來的。所以產生貢獻之後,記得賦值為0,這樣就不會對它的父親區間產生貢獻了。

**如下:

#include#include#include#include#include#define maxn 2000010

using namespace std;

int n,m,k;

long long ans=0;

struct nodenode[maxn];

struct node2t[maxn<<2];

inline bool cmp(struct node x,struct node y)

inline int ls(int x)

inline int rs(int x)

inline void push_up(int x)

inline void build(int x,int l,int r)

int mid=(l+r)>>1;

build(ls(x),l,mid);

build(rs(x),mid+1,r);

push_up(x);

}inline void solve(int x,int k)

inline void push_down(int x)

}inline int update_query(int x,int ll,int rr)

int cur_ans=0;

push_down(x);

cur_ans+=update_query(ls(x),ll,rr);

cur_ans+=update_query(rs(x),ll,rr);

push_up(x);

return cur_ans;

}push_down(x);

int mid=(l+r)>>1;

int cur_ans=0;

if(ll<=mid) cur_ans+=update_query(ls(x),ll,rr);

if(midnode[i].r)

ans+=1ll*cur_ans*node[i].c*node[i].c;

//printf("i=%d ans=%lld\n",i,ans);

}printf("%lld\n",ans);

return 0;

}

SHOI2013 超級跳馬

我是常年遊蕩於題解區的幽靈。直觀的想法就是字首和 差分優化dp,但還有些比較奇妙的方法or trick f i j f i 1 j 1 f i 1 j f i 1 j 1 color 因為可以一步跳到 f i j 的狀態也可以一步跳到 f i 2 j 反過來也成立 只考慮從左邊某個特定的列的轉移矩陣...

矩陣乘 Shoi2013 超級跳馬

問題 f shoi2013 超級跳馬 時間限制 1 sec 記憶體限制 256 mb 題目描述 現有乙個n行m列的棋盤,乙隻馬欲從棋盤的左上角跳到右下角。每一步它向右跳奇數列,且跳到本行或相鄰行。跳越期間,馬不能離開棋盤。例如,當n 3,m 10時,下圖是一種可行的跳法。試求跳法種數mod 3001...

bzoj 4417 Shoi2013 超級跳馬

題意 現有乙個n行m列的棋盤,乙隻馬欲從棋盤的左上角跳到右下角。每一步它向右跳奇數列,且跳到本行或相鄰行。試求跳法種數mod 30011。題解 dp 矩陣乘法 快速冪 設f i j 表示走到第2i 1列,第 j 行的方案數,g i j 表示走到第2i 列,第j行的方案數。那麼f i j k 1i 1...