題意:給出乙個有序集合,3種操作。插入乙個數,刪除乙個數,都保證序列有序。以及求和
其中求和是將下標%5==3的所有數求和;
題解: 線段樹 + 離散化 + 離線處理
一開始也是想的 線段樹 ,但是 這個和以前的 做過的 乙個線段樹 不同的 是 ,如果 我們 刪除 乙個 元素後 ,那麼 他的 下標 將會 改變 ,比賽是 不知 如何下手 。。。。。
同樣 是 用 5棵線段樹 維護 ,s[0]表示 %5 == 1 的 下標,其他 依次類推 cnt,記錄 子樹的 元素個數。
想要得到該區間內所有模5等3所有元素的和,左孩子可以求到,兩個孩子相互獨立,所以求右孩子需要知道(左子樹含有 )多少個元素,因為這樣分開求的時候,我們才知道 求右孩子時應該求下標模5等幾()的所有元素的和。
假如我們 求 i == 3 時 (表示 %5 == 4),對於 左子樹 我們 直接 求 就可以 ,但是 對於 右子樹,我們 要知道 在 i== 3 的 情況下 ,右子樹的 元素的下標 應該 是 %5 == 幾?
p[x].s[i] = p[x*2].s[i] + p[x*2+1].s[((i - p[x*2].cnt)%5 + 5)% 5];
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define min(a,b) a#define max(a,b) a>b?a:b
#define cl(a,num) memset(a,num,sizeof(a));
#define eps 1e-12
#define inf 10000000
//freopen("data.txt","r",stdin);
const
double pi = acos(-1.0);
typedef __int64 ll;
const
int maxn = 101000 ;
using
namespace std;
char c[6];
struct node
p[maxn*4] ;
ll a[maxn],b[maxn],tp[maxn] ;
void build(int x,int l,int r)
void add(int x,int pos,int k)
int mid = (p[x].l + p[x].r) >> 1;
if(pos <=mid )add(x*2,pos,k);
else add(x*2+1,pos,k);
for(int i = 0 ; i< 5;i++)
}int main()
if(c[0] == 'd')
if(c[0] == 's')
}sort(a,a+num) ;
int tot = unique(a,a+num) - a ;
build(1,0,tot - 1);
for(i = 0 ; i< n;i++)
if(tp[i] == 1)
if(tp[i] == 2)
printf("
%i64d\n
",p[1].s[2]);}}
}
hdu 4288 Coder(單點操作,查詢)
題意 三種操作 1.add x add the element x to the set 2.del x remove the element x from the set 3.sum find the digest sum of the set.the digest sum should be u...
無聊題目大紀實(HDU 4288 Coder)
這神題,暴力陣列可過,vector可過,線段樹可過。時限拉的太長了,所以就成水題了。不過比賽的時候真的沒敢用陣列暴力寫。說說線段樹的思路吧。對樹的每個節點 l,r,cnt,sum 5 分別表示左區間,右區間,這段區間上的點數,這段區間上sum x 5 的和。先把所有的資料都讀入,然後離散化,去掉重複...
hdu4288 Coder(線段樹單點更新)
題意 支援增刪,查操作,最後的序列式遞增的。做法 主要是如何維護mod5的sum值,這裡左兒子可以不用管,關鍵是右兒子的處理,可以假設右兒子有t個節點,左兒子有cnt個節點,則令 t cnt mod 5 i 則tmod5 i cnt mod 5 mod 5 所以剩下的就是維護每個節點的節點總數以及相...