周任务:
算法任务:
树状数组
具体任务:
我康了康pl大佬的博客,才发现我的周任务博客这么不友好,可能也没想谁看吧,以后除了模板题都单独写博客。
HDU1166——敌兵布阵
模板题不说啥了啊
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn = 1e5+5;
int N,sum[maxn],a[maxn];
int lowbit(int x){
return x&-x;
}
void Updata(int pos,int v){
int ans = 0,index = pos;
while(index<=N){
sum[index] += v;
index+=lowbit(index);
}
}
int Query(int pos){
int ans = 0;
while(pos){
ans+=sum[pos];
pos-=lowbit(pos);
}
return ans;
}
int main(){
int T,cnt = 0;
scanf("%d",&T);
while(T--){
cnt++;
printf("Case %d:\n",cnt);
scanf("%d",&N);
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
for(int i = 1;i <= N;i++)
scanf("%d",&a[i]);
for(int i = 1;i <= N;i++){
Updata(i,a[i]);
}
while(1){
string str;
cin >> str;
if(str=="Add"){
int p,v;
scanf("%d%d",&p,&v);
Updata(p,v);
}
else if(str=="Sub"){
int p,v;
scanf("%d%d",&p,&v);
Updata(p,-v);
}
else if(str=="Query"){
int l,r;
scanf("%d%d",&l,&r);
int ans = Query(r) - Query(l-1);
printf("%d\n",ans);
}
else break;
}
}
return 0;
}
POJ2299——Ultra-QuickSort
虽然不难啊,但是博客链接还是得有
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 5e5+5;
typedef long long ll;
int N,a[maxn],disc[maxn],sum[maxn];
int lowbit(int x){
return x&-x;
}
void Updata(int p,int v){
while(p <= N){
sum[p]+=v;
p+=lowbit(p);
}
}
ll Query(int p){
int ans = 0;
while(p){
ans+=sum[p];
p-=lowbit(p);
}
return ans;
}
int main(){
while(~scanf("%d",&N)){
if(N==0)break;
memset(sum,0,sizeof(sum));
for(int i = 1;i <= N;i++){
scanf("%d",&a[i]);
disc[i] = a[i];
}
sort(disc + 1,disc + 1 + N);
ll ans = 0;
for(int i = 1;i <= N;i++){
int tmp = lower_bound(disc + 1,disc + 1 + N,a[i]) - disc;
Updata(tmp,1);
ans += i - Query(tmp);
}
printf("%lld\n",ans);
}
return 0;
}
2019牛客多校训练营第七场E——Find the median
这题我想说我开始不知道怎么用树状数组写(区间修改的事),用线段树写了(神奇的Bug搞了好久,一气之下重写,一发就过了),后遂发现树状数组可以实现区间修改,但是仍旧觉得不好写,又寻得一篇博客,记录了神奇的解法,完全不需要数学推导,代码贼短,于是依葫芦画瓢,自己写了一遍。
线段树博客
树状数组博客
线段树代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 8e5+5;
int N;
int X1,X2,Y1,Y2,A1,A2,B1,B2,C1,C2,M1,M2;
int L[maxn<<1],R[maxn<<1],disc[maxn<<1],lazy[maxn<<2];
ll Tree[maxn<<2];
void PushDown(int L,int R,int index){
int Mid = (L + R)>>1;
lazy[index<<1] += lazy[index];
lazy[index<<1|1] += lazy[index];
Tree[index<<1] += lazy[index]*(disc[Mid + 1] - disc[L]);
Tree[index<<1|1] += lazy[index]*(disc[R + 1] - disc[Mid + 1]);
lazy[index] = 0;
}
void Updata(int L,int R,int index,int l,int r){
if(l<=L&&R<=r){
Tree[index] += (disc[R + 1] - disc[L]);
lazy[index] += 1;
return;
}
if(lazy[index])PushDown(L,R,index);
int Mid = (L + R)>>1;
if(r<=Mid)Updata(L,Mid,index<<1,l,r);
else if(l>Mid)Updata(Mid + 1,R,index<<1|1,l,r);
else {
Updata(L,Mid,index<<1,l,Mid);
Updata(Mid + 1,R,index<<1|1,Mid + 1,r);
}
Tree[index] = Tree[index<<1] + Tree[index<<1|1];
}
int Query(ll K,int L,int R,int index){
if(L==R){
// printf("%lld %d %d %d\n",K,L,R,index);
int num = Tree[index]/(disc[R + 1] - disc[L]);
return disc[L] + (K-1)/num;
}
// printf("%lld %d %d %d\n",K,L,R,index);
// printf("%d\n",Tree[index<<1]);
int Mid = (L + R)>>1;
if(lazy[index])PushDown(L,R,index);
if(K<=Tree[index<<1])return Query(K,L,Mid,index<<1);
else return Query(K-Tree[index<<1],Mid + 1,R,index<<1|1);
}
int main(){
scanf("%d",&N);
scanf("%d%d%d%d%d%d",&X1,&X2,&A1,&B1,&C1,&M1);
scanf("%d%d%d%d%d%d",&Y1,&Y2,&A2,&B2,&C2,&M2);
L[1] = min(X1,Y1) + 1;
R[1] = max(X1,Y1) + 1;
L[2] = min(X2,Y2) + 1;
R[2] = max(X2,Y2) + 1;
ll x,y,cnt = 0;
for(int i = 3;i <= N;i++){
x = ((1ll*A1 * X2 % M1 + 1ll * B1 * X1 %M1)%M1 + C1)%M1;
y = ((1ll*A2 * Y2 % M2 + 1ll * B2 * Y1 %M2)%M2 + C2)%M2;
X1 = X2;X2 = x;
Y1 = Y2;Y2 = y;
L[i] = min(x,y) + 1;
R[i] = max(x,y) + 1;
}
for(int i = 1;i <= N;i++){
disc[++cnt] = L[i];
disc[++cnt] = R[i] + 1;
// printf("%d %d\n",L[i],R[i]);
}
memset(Tree,0,sizeof(Tree));
memset(lazy,0,sizeof(lazy));
sort(disc + 1,disc + 1 + cnt);
int count = unique(disc + 1,disc + 1 + cnt) - disc - 1;
ll All = 0;
for(int i = 1;i <= N;i++){
int l,r;
All += R[i] - L[i] + 1;
l = lower_bound(disc + 1,disc + count + 1,L[i]) - disc;
r = lower_bound(disc + 1,disc + count + 1,R[i] + 1) - disc;
// printf("%d %d\n",l,r);
Updata(1,count,1,l,r-1);
printf("%d\n",Query((All+1)/2,1,count,1));
}
return 0;
}
树状数组代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 8e5+5;
const int INF = 1e9;
int N;
int X1,X2,Y1,Y2,A1,A2,B1,B2,C1,C2,M1,M2;
int L[maxn],R[maxn],disc[maxn<<1];
ll b1[maxn],b2[maxn],cnt = 0;
int lowbit(int x){
return x&-x;
}
void Updata(ll a[],int pos,int value){
while(pos <= cnt){
a[pos] += value;
pos += lowbit(pos);
}
}
ll Query(ll a[],int x){
ll ans = 0;
while(x){
ans += a[x];
x -= lowbit(x);
}
return ans;
}
int main(){
scanf("%d",&N);
scanf("%d%d%d%d%d%d",&X1,&X2,&A1,&B1,&C1,&M1);
scanf("%d%d%d%d%d%d",&Y1,&Y2,&A2,&B2,&C2,&M2);
L[1] = min(X1,Y1) + 1;
R[1] = max(X1,Y1) + 1;
L[2] = min(X2,Y2) + 1;
R[2] = max(X2,Y2) + 1;
ll x,y;
for(int i = 3;i <= N;i++){
x = ((1ll*A1 * X2 % M1 + 1ll * B1 * X1 %M1)%M1 + C1)%M1;
y = ((1ll*A2 * Y2 % M2 + 1ll * B2 * Y1 %M2)%M2 + C2)%M2;
X1 = X2;X2 = x;
Y1 = Y2;Y2 = y;
L[i] = min(x,y) + 1;
R[i] = max(x,y) + 1;
}
for(int i = 1;i <= N;i++){
disc[++cnt] = L[i];
disc[++cnt] = R[i] + 1;
// printf("%d %d\n",L[i],R[i]);
}
memset(b1,0,sizeof(b1));
memset(b2,0,sizeof(b2));
sort(disc + 1,disc + 1 + cnt);
cnt = unique(disc + 1,disc + 1 + cnt) - disc - 1;
ll All = 0;
for(int i = 1;i <= N;i++){
int l,r;
All += R[i] - L[i] + 1;
l = lower_bound(disc + 1,disc + cnt + 1,L[i]) - disc;
r = lower_bound(disc + 1,disc + cnt + 1,R[i] + 1) - disc;
Updata(b1,l,-L[i]);
Updata(b1,r,R[i]+1);
Updata(b2,l,1);
Updata(b2,r,-1);
int left = 1,right = INF;
ll pd = (All + 1)/2;
while(left < right){
int mid = (left + right)>>1;
int pos = upper_bound(disc + 1,disc + cnt + 1,mid) - disc - 1;
ll tmp = Query(b1,pos) + Query(b2,pos)*(mid + 1);
if(tmp < pd) left = mid + 1;
else right = mid;
}
printf("%d\n",left);
}
return 0;
}
最后一题先给别人的代码,日后自己在写吧:
#include <bits/stdc++.h>
using namespace std;
typedef long long lint;
const int maxn = 100005;
const int maxm = 100005;
int E[maxn],L[maxn],C[maxn],d[maxn],mx;
vector<int> st[maxn],en[maxn];
set<int> se;
void init( int n ){
se.clear();
for( int i = 0; i<= n;i++ ) st[i].clear(),en[i].clear();
}
struct fanwick{
lint limit,b[200005];
void init( int mx ){
limit = mx+1;
for( int i = 0;i <= limit;i++ ) b[i] = 0;
}
int lowbit(int x){
return x&-x;
}
void add( int x,lint v ){
while(x<=limit){
b[x] += v;
x += lowbit(x);
}
}
lint ask( lint x ){
lint res = 0;
if( x > limit ) x = limit;
while(x){
res += b[x];
x -= lowbit(x);
}
return res;
}
lint query( int l,int r ){
if( l > r ) return 0;
return ask(r)-ask(l-1);
}
}g1,g2;
lint ans = 0;
void solve( int x ){
if( se.size() ){
auto p = se.begin();
if( L[x] && *p >= (C[x]-E[x]+L[x]-1)/L[x] ) ans += C[x];
else ans += E[x] + L[x]* *p;
ans += g2.ask( d[x]-1 ) * L[x];
ans += g1.query( d[x],g1.limit ) * C[x] ;
}
}
int main(){
int n,T,l,r;
scanf("%d",&T);
for( int tt = 1;tt <= T;tt++ ){
printf("Case #%d: ",tt);
ans = mx = 0;
scanf("%d",&n);init(n);
for( int i = 1;i <= n;i++ ) {
scanf("%d%d%d",&E[i],&L[i],&C[i]);
d[i] = L[i] ?(C[i] + L[i]-1)/L[i] : 1e6+1 ;
}
int m,t;
scanf("%d",&m);
for(int i = 1;i <= m;i++1 ) {
scanf("%d%d%d",&t,&l,&r);
st[l].push_back( t );
en[r+1].push_back(t);
mx = max( mx,t );
}
g1.init(mx);g2.init(mx);
for( int i = 1;i <= n;i++ ){
for( auto x : st[i] ){
se.insert(x);
auto p = se.find(x);
auto pre = p,suf = p;
if( p != se.begin() ) --pre;
if( p != se.end() ) ++suf;
if( p != se.begin() ){
int dt = *p-*pre;
g1.add( dt,1 );g2.add( dt,dt );
}
if( suf != se.end() ){
int dt = *suf-*p;
g1.add( dt,1 );g2.add( dt,dt );
if(p!=se.begin()){
int dt = *suf-*pre;
g1.add( dt,-1 );g2.add( dt,-dt );
}
}
}
for( auto x : en[i] ){
auto p = se.find( x );
auto suf = p,pre = p;
if( p != se.begin() )--pre;
if( p != se.end() ) ++suf;
if( p != se.begin() ){
int dt = *p - *pre;
g1.add( dt,-1 );g2.add( dt,-dt );
}
if( suf != se.end() ){
int dt = *suf - *p;
g1.add( dt,-1 );g2.add( dt,-dt );
if( p != se.begin() ){
dt = *suf - *pre;
g1.add( dt,1 );g2.add( dt,dt );
}
}
se.erase(p);
}
solve(i);
}
printf("%lld\n",ans);
}
return 0;
}