【洛谷2468】[SDOI2010] 粟粟的書架(二合一)
大致題意: 問你選取一個矩形區間內至少幾個數,才能使它們的和。
二合一
根據資料範圍,比較顯然能看出它是一道二合一的題目。
對於第一種情況,,我們可以用字首和+二分去做。
而對於另一種情況,,就需要使用主席樹了。
字首和+二分
先來講講第一種情況。
我們可以用來表示 到的矩形區間內的數的總和,然後用來表示 到的矩形區間內的數的個數。
這樣一來,如何二分應該不用多說了吧!
直接二分的大小即可。
主席樹
顯然,對於,我們可以用主席樹來維護。
我們可以直接在樹上查詢,求出最少的和的數的個數。
這應該是主席樹比較經典的操作了。
如果不會,可以參考程式碼。
程式碼
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define P 1000
using namespace std;
int n,m;
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_SumSolver//字首和+二分
{
private:
#define N 200
#define get_val(array,x1,y1,x2,y2,v) (array[x2][y2][v]-array[x1-1][y2][v]-array[x2][y1-1][v]+array[x1-1][y1-1][v])//求出區間內的值
int a[N+5][N+5],sum[N+5][N+5][P+5],tot[N+5][N+5][P+5];
public:
inline void Solve()
{
register int i,j,k,Q,x1,y1,x2,y2,v,l,r,mid;
for(F.read(Q),i=1;i<=n;++i) for(j=1;j<=m;++j)//讀入+預處理
{
for(F.read(a[i][j]),k=0;k<=a[i][j];++k) sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+a[i][j],tot[i][j][k]=tot[i-1][j][k]+tot[i][j-1][k]-tot[i-1][j-1][k]+1;
for(;k<=P;++k) sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k],tot[i][j][k]=tot[i-1][j][k]+tot[i][j-1][k]-tot[i-1][j-1][k];
}
while(Q--)
{
F.read(x1),F.read(y1),F.read(x2),F.read(y2),F.read(v);
if(get_val(sum,x1,y1,x2,y2,0)<v) {F.write_string("Poor QLW\n");continue;}//特判是否無解
for(mid=(l=0)+(r=P+1)+1>>1;l+1<r;mid=l+r+1>>1) get_val(sum,x1,y1,x2,y2,mid)>=v?l=mid:r=mid;//二分
F.write(get_val(tot,x1,y1,x2,y2,l)-(get_val(sum,x1,y1,x2,y2,l)-v)/l),F.write_char('\n');//輸出答案
}
}
}SumSolver;
class Class_ChairmanTreeSolver//主席樹
{
private:
#define M 500000
#define LogP 10
int a[M+5],sum[M+5];
class Class_ChairmanTree
{
private:
int n,v,tot,Root[M+5];
struct Tree
{
int Sum,Size,Son[2];
}node[P*LogP+5];
inline void Build(int l,int r,int &rt)//建樹
{
if(!rt) rt=++tot;if(!(l^r)) return;
register int mid=l+r>>1;
Build(l,mid,node[rt].Son[0]),Build(mid+1,r,node[rt].Son[1]);
}
inline void upt(int l,int r,int &rt,int lst,int val)//修改
{
node[rt=++tot]=node[lst],node[rt].Sum+=val,++node[rt].Size;
if(!(l^r)) return;
register int mid=l+r>>1;
val<=mid?upt(l,mid,node[rt].Son[0],node[lst].Son[0],val):upt(mid+1,r,node[rt].Son[1],node[lst].Son[1],val);
}
inline int qry(int l,int r,int rt1,int rt2,int v)//查詢
{
if(!(l^r)) return (v+l-1)/l;
register int mid=l+r>>1,t=node[node[rt2].Son[1]].Sum-node[node[rt1].Son[1]].Sum;
if(t<v) return node[node[rt2].Son[1]].Size-node[node[rt1].Son[1]].Size+qry(l,mid,node[rt1].Son[0],node[rt2].Son[0],v-t);
return qry(mid+1,r,node[rt1].Son[1],node[rt2].Son[1],v);
}
public:
inline void Init(int len) {n=len,Build(1,n,Root[0]);}
inline void Insert(int val) {++v,upt(1,n,Root[v],Root[v-1],val);}
inline int Query(int ql,int qr,int v) {return qry(1,n,Root[ql-1],Root[qr],v);}
}ChairmanTree;
public:
inline void Solve()
{
register int i,Q,x,y,v;
for(ChairmanTree.Init(P),F.read(Q),i=1;i<=m;++i) F.read(a[i]),sum[i]=sum[i-1]+a[i],ChairmanTree.Insert(a[i]);//讀入,預處理字首和,然後將該元素插入主席樹
while(Q--)
{
F.read(x),F.read(x),F.read(y),F.read(y),F.read(v);
if(sum[y]-sum[x-1]<v) {F.write_string("Poor QLW\n");continue;}//特判是否無解
F.write(ChairmanTree.Query(x,y,v)),F.write_char('\n');//在主席樹上查詢
}
}
}ChairmanTreeSolver;
int main()
{
if(F.read(n),F.read(m),n^1) SumSolver.Solve();else ChairmanTreeSolver.Solve();
return F.end(
相關推薦
【洛谷2468】[SDOI2010] 粟粟的書架(二合一)
點此看題面
大致題意: 問你選取一個矩形區間內至少幾個數,才能使它們的和≥Hi\ge H_i≥Hi。
二合一
根據資料範圍,比較顯然能看出它是一道二合一的題目。
對於第一種情況,R,C≤200R,C\le 200R,C≤200,我們可以用字首和+二分去做。
【洛谷2216】[HAOI2007] 理想的正方形(二維RMQ)
點此看題面
大致題意: 求出一個矩陣中所有n∗nn*nn∗n正方形中極差的最小值。
另一種做法
聽說這題可以用單調佇列去做,但是我寫了一個二維RMQRMQRMQ。
二維RMQRMQRMQ
RMQRM
【洛谷 P2216】 [HAOI2007]理想的正方形(二維ST表)
memset == string using 二維 size 做出 ++ read 題目鏈接
做出二維\(ST\)表,然後\(O(n^2)\)掃一遍就好了。
#include <cstdio>
#include <cstring>
#include
2018.11.07【CQOI2011】【BZOJ3295】【洛谷P3157】動態逆序對(樹狀陣列套動態開點線段樹)
BZOJ傳送門
洛谷傳送門
解析:
首先我們可以通過一個線段樹求出逆序對個數,然後就是亂搞的時間了。
顯然每次刪除一個數,需要我們查詢前面比他大的數的個數和後面比他小的數的個數,這個就是裸的樹套樹了。這道題可以用樹狀陣列套線段樹動態開點。
程式碼:
#
【洛谷1580】yyy loves Easter_Egg I(字串處理題)
點此看題面
大致題意: 略。(一道模擬題,自己去看題面吧)
幾個字元陣列函式
純粹是一道字串處理題,就當是學了一下各種與字元陣列相關的函式吧!
\(gets()\):這個是比較常用的函式,就是讀入一行的字元。
\(strlen()\):求出字元陣列的長度。
\(sscanf()\):從一個字元
【洛谷 P3165】 [CQOI2014]排序機械臂 (Splay)
題目連結 debug了\(N\)天沒debug出來,原來是找後繼的時候沒有pushdown。。。 眾所周知,,Splay中每個編號對應的節點的值是永遠不會變的,因為所有旋轉、翻轉操作改變的都是父節點和子節點的指標。 於是記錄每個數在\(Splay\)中的位置,然後按大小升序排序,每次把第\(i\)個數轉到根,
【洛谷 P4008】 [NOI2003]文字編輯器 (Splay)
題目連結 \(Splay\)先練到這吧(好像還有道毒瘤的維護數列誒,算了吧) 記錄下游標的編號,維護就是\(Splay\)基操了。 另外資料有坑,資料是\(Windows\)下生成了,回車是'\n\r',我就被坑了。
#include <cstdio>
#include <algorith
【洛谷1117_BZOJ4650】[NOI2016] 優秀的拆分(雜湊_字尾陣列_RMQ)
題目:
洛谷1117
分析:
定義把我校某兔姓神犇Tzz和他的妹子拆分,為“優秀的拆分”
隨便寫個雜湊就能有\(95\)分的好成績……
我的\(95\)分做法比fei較chang奇葩,不想浪費時間的可以忽略解法一qwq
解法一:
用\(n\)個vector記錄對於每個點\(i\),哪些長度\(l
【洛谷 P2756】 飛行員配對方案問題(二分圖匹配,最大流)
題目連結 這不是裸的二分圖匹配嗎? 而且匈牙利演算法自帶記錄方案。。 但既然是網路流24題,那就用網路流來做吧。 具體就是從源點向左邊每個點連一條流量為1的邊,兩邊正常連邊,流量都是一,右邊所有點向匯點連一條流量為1的邊,然後跑\(Dinic\)就行了。 怎麼記錄方案?列舉左邊所有點連的所有邊,如果剩餘流量為
【洛谷1501】[國家集訓隊] Tree II(LCT維護懶惰標記)
點此看題面
大致題意: 有一棵初始邊權全為\(1\)的樹,四種操作:將兩點間路徑邊權都加上一個數,刪一條邊、加一條新邊,將兩點間路徑邊權都加上一個數,詢問兩點間路徑權值和。
序列版
這道題有一個序列版:【洛谷3373】【模板】線段樹 2。
看題目就知道是一道線段樹板子題。
這種題目移到樹上路徑中
【洛谷5113】Sabbat of the witch(毒瘤分塊)
點此看題面
大致題意: 給你一個序列,要你支援三種操作:區間賦值,區間求和,撤回之前任一區間賦值操作。
分塊
這道題應該是一道十分毒瘤的分塊題。
這道題要用到的演算法並不是很難,但是思維難度是真的高。
大致思路就是對於每一個塊維護一大堆資訊,各用一個棧儲存對每個塊的賦值操作,並開一個鄰接表來儲存
2018.12.30【國家集訓隊】【洛谷P1903】數顏色 / 維護佇列(帶修莫隊)
傳送門
解析:
這道題好像以前在BZOJ上做過。
但是因為BZOJ資料較水,所以被我複雜度不對的程式碼搞過去了。。
真正的排序策略應該是這樣的:
塊大小設定成
n
【洛谷 P5110】 塊速遞推(矩陣加速,分塊打表)
題目連結 掌握了分塊打表法了。原來以前一直想錯了。。。 塊的大小\(size=\sqrt n\),每隔\(size\)個數打一個表,還要在\(0\text{~}size-1\)每個數打一個表。 然後就可以做到\(O(1)\)查詢了。
比如要求\(A^{n}\),只需要算出\(biao[n/size]*pow
【洛谷2756】飛行員配對方案問題(二分圖匹配,網路流24題)
前言
網路流24題還是要做完吧!
題解
這是一道模板題,這裡主要講一下怎麼匈牙利二分圖匹配:
對於左邊的列舉每一次選的左邊的人
對於右邊與他有連邊的那麼就是能換則換,不然就不換
最後統計出來的就是\(ans\)
差不多就是這樣子了吧。
#include<stdio.h>
【洛谷2774】 方格取數問題(網絡流24題,最小割)
define line sin 方格取數 inline getch string.h 一個 最小割 前言
為什麽他們能夠切的那麽快啊。
Solution
雖然我不會怎麽區分最大流和最小費用最大流,但是最大流可以看成最小割,這樣子就好區分一些。
考慮這個東西相當於是二分圖求一
【洛谷 P4051】 [JSOI2007]字符加密(後綴數組)
num ons 鏈接 ring tdi href [1] show 。。 題目鏈接
兩眼題。。
第一眼裸SA
第二眼要復制一倍再跑SA。
一遍過。。
#include <cstdio>
#include <cstring>
#include <
【洛谷 P1502】 窗口的星星(掃描線)
double fine define print 離散化 while down namespace names 題目鏈接
把每個星星作為左下角,做出長為\(w-0.5\),寬為\(h-0.5\)的矩形。
\(-0.5\)是因為邊框上的不算。
離散化\(y\)坐標。
記錄\(
【洛谷 P3191】 [HNOI2007]緊急疏散EVACUATE(二分答案,最大流)
size ems ons ++ pri scan += define while 題目鏈接
sb錯誤調了3hour+。。
bfs預處理出每個\(.\)到每個\(D\)的最短距離。
二分時間\(t\),把每個\(D\)拆成\(t\)個點,這\(t\)個點兩兩連邊,流量\(IN
【洛谷 P2604】 [ZJOI2010]網絡擴容(最大流,費用流)
clas printf 簡單 edge esp ++i amp https next 題目鏈接
第一問就是簡單的最大流。
第二問,保留第一問求完最大流的殘量網絡。
然後新建一個源點,向原源點連一條流量為k,費用為0的邊。
然後所有邊重新連一起(原來的邊保留),費用為題目所給
【洛谷1361】 小M的作物(最小割)
ini main 每一個 題目 lse 貢獻 sum 代碼 mem 傳送門
洛谷
Solution
這是一個比較實用的套路,很多題目都有用,而且這個套路難以口胡出來。
考慮把每一個附加貢獻重新建一個點,然後向必需的點連邊,流量為val。
然後直接種植的從源點向這個點連,流量