[uoj228]基礎資料結構練習題 解題報告
這題好厲害呀。。
看完題一看。。相鄰兩個數開根號的話差會由a-b變成
\sqrt a -\sqrt b
,相當於除了一個\sqrt a+\sqrt b
,這樣的話很快差就要變成0了,傻逼題呀!這樣只需搞一棵線段樹,如果一個區間都是一個數了,就直接開根號,相當於打個覆蓋標記,否則的話就遞迴下去;這樣遞迴下去的條件是一個區間有相鄰兩個數差不為0,這樣會使得原區間裂成\ \lg
區間長度\
個小區間,而對於一個差而言只會造成這種情況\lg \lg n
次;區間加的話就相當於是重置了兩端的差,所以時間複雜度是O((n+m)\lg n\lg \lg n)
。 然後寫完一交,70.
一看資料。。差為1…臥槽?!
原來當差為1的時候開完根號可能差還是為1,就是如果a是一個完全平方數,b=a-1,那麼
\lfloor \sqrt a \rfloor=\lfloor \sqrt b \rfloor +1
。但是隻有差為1才會出現這種情況,因為如果\lfloor \sqrt a \rfloor=\lfloor \sqrt b \rfloor +2
的話,a-b最小的情況也是a=9,b=3,a-b=6了。
這個hack點有點強啊。。
於是我想,原來我是當一個區間所有數相同的時候就統一處理,那麼就改一下,改成所有數差≤1時統一處理吧,記一下最大值、最小值、最大值出現次數。。然後就改呀改,終於ac了。
然後膜拜了一個大神的題解,原來差為1的時候只需要把它看成區間減操作就行了!我果然是傻逼。。。
程式碼:
#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstring>
#include<cmath>
const int N=1e5+5,M=1e5+5;
typedef long long LL;
int a[N];
char * cp=(char *)malloc(5000000);
void in(int &x){
while(*cp<'0'||*cp>'9')++cp;
for(x=0;*cp>='0'&&*cp<='9';)x=x*10+(*cp++^'0');
}
char * os=(char *)malloc(2000000),* op=os;
void out(LL x)
{
if(x)
{
out(x/10);
*op++=x%10^'0';
}
}
struct SS
{
LL sum;
LL delta;
LL max,min;
int maxcnt;
LL cover0,cover1;
}segt[N<<2];
#define lson node*2,l,(l+r)/2
#define rson node*2+1,(l+r)/2+1,r
#define self node,l,r
void out(int node,int l,int r){
printf("Segt(%d,[%d,%d])={sum=%I64d,delta=%I64d,max=%I64d,min=%I64d,maxcnt=%d,cover0=%I64d,cover1=%I64d}\n",node,l,r,segt[node].sum,segt[node].delta,segt[node].max,segt[node].min,segt[node].maxcnt,segt[node].cover0,segt[node].cover1);
}
void pushup(int node)
{
segt[node].sum=segt[node<<1].sum+segt[node<<1|1].sum;
segt[node].max=max(segt[node<<1].max,segt[node<<1|1].max);
segt[node].min=min(segt[node<<1].min,segt[node<<1|1].min);
segt[node].maxcnt=0;
if(segt[node<<1].max==segt[node].max)segt[node].maxcnt+=segt[node<<1].maxcnt;
if(segt[node<<1|1].max==segt[node].max)segt[node].maxcnt+=segt[node<<1|1].maxcnt;
}
void cover_paint(int node,int l,int r,LL cover0,LL cover1)
{
//printf("cover_paint(%d,[%d,%d],%I64d,%I64d)\n",node,l,r,cover0,cover1);
segt[node].delta=0;
segt[node].sum=cover0*segt[node].maxcnt+(r-l+1-segt[node].maxcnt)*cover1;
segt[node].max=segt[node].cover0=cover0,segt[node].min=segt[node].cover1=cover1;
if(cover0==cover1)segt[node].maxcnt=r-l+1;
}
void delta_paint(int node,int l,int r,LL delta)
{
segt[node].sum+=(r-l+1)*delta;
segt[node].max+=delta,segt[node].min+=delta;
if(segt[node].cover0)segt[node].cover0+=delta,segt[node].cover1+=delta;
else segt[node].delta+=delta;
}
void pushdown(int node,int l,int r)
{
if(segt[node].cover0)
{
LL lcover=segt[node<<1].max>=segt[node<<1|1].max?segt[node].cover0:segt[node].cover1,rcover=segt[node<<1|1].max>=segt[node<<1].max?segt[node].cover0:segt[node].cover1;
cover_paint(lson,lcover,segt[node<<1].max==segt[node<<1].min?lcover:segt[node].cover1);
cover_paint(rson,rcover,segt[node<<1|1].max==segt[node<<1|1].min?rcover:segt[node].cover1);
segt[node].cover0=0;
}
else if(segt[node].delta)
{
delta_paint(lson,segt[node].delta),delta_paint(rson,segt[node].delta);
segt[node].delta=0;
}
}
void build(int node,int l,int r)
{
if(l==r)segt[node]=(SS){a[l],0,a[l],a[l],1};
else
{
build(lson),build(rson);
pushup(node);
}
//out(self);
}
void add(int node,int l,int r,int L,int R,int x)
{
if(L<=l&&r<=R)delta_paint(self,x);
else
{
pushdown(self);
if(L<=(l+r)/2)add(lson,L,R,x);
if(R>(l+r)/2)add(rson,L,R,x);
pushup(node);
}
//out(self);
}
void sqroot(int node,int l,int r,int L,int R)
{
if(L<=l&&r<=R&&segt[node].max-segt[node].min<=1)cover_paint(self,(LL)sqrt(segt[node].max),(LL)sqrt(segt[node].min));
else
{
pushdown(self);
if(L<=(l+r)/2)sqroot(lson,L,R);
if(R>(l+r)/2)sqroot(rson,L,R);
pushup(node);
}
//out(self);
}
LL query(int node,int l,int r,int L,int R){
//out(self);
if(L<=l&&r<=R)return segt[node].sum;
else
{
pushdown(self);
LL ans=0;
if(L<=(l+r)/2)ans+=query(lson,L,R);
if(R>(l+r)/2)ans+=query(rson,L,R);
return ans;
}
}
int main(){
freopen("uoj228.in","r",stdin);
freopen("uoj228.out","w",stdout);
fread(cp,1,5000000,stdin);
int n,m;
in(n),in(m);
for(int i=1;i<=n;++i)in(a[i]);
build(1,1,n);
int opt,l,r,x;
while(m--){
//puts("----------");
in(opt),in(l),in(r);
switch(opt){
case 1:
in(x);
add(1,1,n,l,r,x);
break;
case 2:
sqroot(1,1,n,l,r);
break;
case 3:
out(query(1,1,n,l,r));
*op++='\n';
break;
}
}
fwrite(os,1,op-os,stdout);
}
總結:
①下取整和不下取整還是有區別的。。一定要考慮清楚這個問題。
相關文章
- 資料結構專題練習資料結構
- JAVA 基礎練習題Java
- linux基礎練習題Linux
- Python基礎練習題Python
- 野生前端的資料結構基礎練習(8)——圖前端資料結構
- 野生前端的資料結構基礎練習(4)——字典前端資料結構
- 迷宮問題【資料結構實驗報告】資料結構
- linux基礎練習題、面試題(二)Linux面試題
- P5655 基礎數論函式練習題 題解函式
- 基礎面試題 — 資料結構與演算法面試題資料結構演算法
- 資料結構基礎和演算法題系列總結資料結構演算法
- 9道python基礎練習題Python
- 資料 結構客觀題複習題集
- 資料結構練習題(順序表和單連結串列)C++資料結構C++
- js 中基礎資料結構陣列去重問題JS資料結構陣列
- python基礎(四)----列表、字典練習題Python
- JS資料結構-棧-練習JS資料結構
- 資料結構基礎學習之緒論資料結構
- 50道Java基礎程式設計練習題Java程式設計
- Redis基礎資料結構Redis資料結構
- leetcode演算法資料結構題解---資料結構LeetCode演算法資料結構
- 資料庫精通練習題答案資料庫
- 網路資料庫練習題資料庫
- vue2.0 練習中報錯問題處理(資料繫結錯誤)Vue
- 資料結構基礎學習之線性表資料結構
- [Luogu-P3676]小清新資料結構題-題解資料結構
- 資料結構基礎 連結串列資料結構
- MySQL基礎練習20題,看看你的sql基礎man不manMySql
- javaScript基礎練習題-下拉框製作(JQuery)JavaScriptjQuery
- JavaSE基礎知識分享(二)相關練習題Java
- 資料結構基礎知識資料結構
- 基礎資料結構大賞資料結構
- 資料結構——迴圈佇列PTA習題資料結構佇列
- 資料結構和演算法面試題系列—二叉樹基礎資料結構演算法面試題二叉樹
- Redis基礎——剖析基礎資料結構及其用法Redis資料結構
- 資料結構的練習day1資料結構
- 2015年nefu寒假集訓結構體排序專題解題報告結構體排序
- 資料結構基礎學習之(棧和佇列)資料結構佇列