#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define clr(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define SZ(x) ((int)(x).size())
typedef unsigned long long ull;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int MAXN=5e5+10;
struct BIT{
ll c[MAXN];
int n;
void init(int _n){
n=_n;
rep(i,1,n)c[i]=0;
}
void update(int pos,ll val){
while(pos<=n){
c[pos]+=val;
pos+=pos&-pos;
}
}
ll query(int pos){
ll res=0;
while(pos){
res+=c[pos];
pos-=pos&-pos;
}
return res;
}
}bit;
int main(){
int n,m;
scanf("%d%d",&n,&m);
bit.init(n);
rep(i,1,n){
ll w;
scanf("%lld",&w);
bit.update(i,w);
}
while(m--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1){
bit.update(x,y);
}else{
printf("%lld\n",bit.query(y)-bit.query(x-1));
}
}
return 0;
}
思考:如果是点修改,而不是加减怎么办。
- 用一个辅助数组a[i] 记录当前i位置的值,把这个数修改成x,等同于在i位置加上w,那么有a[i]+w=x 所以w=a[i]-x;
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define clr(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define SZ(x) ((int)(x).size())
typedef unsigned long long ull;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int MAXN=5e5+10;
struct BIT{
ll c[MAXN];
int n;
void init(int _n){
n=_n;
rep(i,1,n)c[i]=0;
}
void update(int pos,ll val){
while(pos<=n){
c[pos]+=val;
pos+=pos&-pos;
}
}
ll query(int pos){
ll res=0;
while(pos){
res+=c[pos];
pos-=pos&-pos;
}
return res;
}
}bit;
int main(){
int n,m;
scanf("%d%d",&n,&m);
bit.init(n);
rep(i,1,n){
ll x;
scanf("%lld",&x);
bit.update(i,x);
bit.update(i+1,-x);
}
while(m--){
int op;
scanf("%d",&op);
if(op==1){
int x,y;
ll k;
scanf("%d%d%lld",&x,&y,&k);
bit.update(x,k);
bit.update(y+1,-k);
}else{
int x;
scanf("%d",&x);
printf("%lld\n",bit.query(x));
}
}
return 0;
}
题意
- n个数 代表第i季剧有j集,问存在多少对(x,y)满足存在x季y集和y季x集。
思路
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pb push_back
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
const int MAXN=2e5+10;
int n;
ll a[MAXN];
void update(int i,int v){
while(i<=n){
a[i]+=v;
i+=i&-i;
}
}
ll query(int i){
ll res=0;
while(i){
res+=a[i];
i-=i&-i;
}
return res;
}
vi v[MAXN];
int x[MAXN];
int main(){
scanf("%d",&n);
ll ans=0;
rep(i,1,n){
scanf("%d",&x[i]);
x[i]=min(x[i],n);
v[min(i-1,x[i])].pb(i);
}
rep(i,1,n){
update(1,1);
update(x[i]+1,-1);
for(auto w:v[i]){
ans+=query(w);
}
}
printf("%I64d",ans);
return 0;
}
题意
思路
#include<cstdio>
#include<cstring>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
const int MAXN=2e5+10;
int n;
int a[MAXN],b[MAXN],c[MAXN],ans[MAXN];
void update(int i,int v){
while(i<=n){
c[i]+=v;
i+=i&-i;
}
}
int findpos(int v){
int sum=0;
int pos=0;
int i=1;
for(;i<n;i<<=1);
for(;i;i>>=1){
if(pos+i<=n&&sum+c[pos+i]<v){
pos+=i;
sum+=c[pos];
}
}
return pos+1;
}
int main(){
while(~scanf("%d",&n)){
memset(c,0,sizeof(c));
rep(i,1,n){
scanf("%d%d",&a[i],&b[i]);
a[i]++;
update(i,1);
}
per(i,n,1){
int pos=findpos(a[i]);
ans[pos]=b[i];
update(pos,-1);
}
rep(i,1,n){
printf("%d ",ans[i]);
}
puts("");
}
return 0;
}
题意
#include<cstdio>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;
const int MAXN=5e5+10;
int cnt[MAXN];
int w[MAXN];
char name[MAXN][15];
int a[MAXN];
struct BIT{
int n;
ll c[MAXN<<1];
void init(int _n){
n=_n;
rep(i,0,n)c[i]=0;
}
void update(int i,ll v){
for(;i<=n;i+=i&-i)c[i]+=v;
}
ll query(int i){
ll s=0;
for(;i;i-=i&-i)s+=c[i];
return s;
}
int findpos(ll v){
ll sum=0;
int pos=0;
int i=1;
for(;i<n;i<<=1);
for(;i;i>>=1){
if(pos+i<=n&&sum+c[pos+i]<v){
sum+=c[pos+i];
pos+=i;
}
}
return pos+1;
}
}bit;
int main(){
rep(i,1,500000){
for(int j=i;j<=500000;j+=i){
cnt[j]++;
}
}
w[1]=1;
rep(i,2,500000){
if(cnt[i]>cnt[w[i-1]]){
w[i]=i;
}else{
w[i]=w[i-1];
}
}
int n,m;
while(~scanf("%d%d",&n,&m)){
bit.init(n);
int k=w[n];
rep(i,1,n){
scanf("%s%d",name[i],&a[i]);
bit.update(i,1);
}
int now=m;
int pos=m;
rep(i,1,k){
if(i==k){
printf("%s %d\n",name[pos],cnt[k]);
break;
}
bit.update(pos,-1);
if(a[pos]>0){
now=(now-2+a[pos]+(n-1))%(n-1)+1;
pos=bit.findpos(now);
}else{
now=now-(-a[pos])%(n-1);
while(now<=0)now+=(n-1);
while(now>(n-1))now-=(n-1);
pos=bit.findpos(now);
}
n--;
}
}
return 0;
}
题意
- 三个操作,1在x时刻添加一个y,2在x时刻减少一个y,3在x时刻查询有几个y
思路
- 因为总操作数只有1e5,离散化动态开树状数组就好了
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
map<int,int> M[MAXN];
map<int,int> vis;
int tot=1;
int n=1e9+10;
void update(int tp,int i,int v){
while(i<=n){
M[tp][i]+=v;
i+=i&-i;
}
}
int query(int tp,int i){
int res=0;
while(i){
res+=M[tp][i];
i-=i&-i;
}
return res;
}
int main(){
int q;
scanf("%d",&q);
while(q--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1&&vis[y]==0){
vis[y]=tot++;
}
if(op==1)update(vis[y],x,1);
if(op==2)update(vis[y],x,-1);
if(op==3)printf("%d\n",query(vis[y],x));
}
return 0;
}