1冊の通は編の木の形の配列を高めて題集をします
19035 ワード
前奏
木の配列の問題をする前に、3つの板の問題をする必要があります.
ボード1——単点修正、区間照会
板子题就不写题解了哈
コード#コード#
板子題2——区間修正、単点照会
コード#コード#
板子題3——区間修正、区間照会
コード#コード#
正式に問題を塗ります!!
T 1——星を数えるUral 1028/loj 10114
問題解
入力時にテーマが並べ替えられているため、並べられたデータであればy軸とは関係なく、現在の星の級数は、その星の前のすべてのx軸がその星のx軸の大きさに等しい数の和より小さいと推理されている.これからは楽しくコードをコードできます~~~
コード#コード#
T 2——校門外の木vijos 1148loj 10115
問題解
この問題を括弧シーケンスに変換し、区間に1つの木を植えることはlの位置に1つを加えることに相当する(,r rの位置に1つの右括弧を加える.2つの木状配列を維持し、1つは左括弧を記録し、1つは右括弧を記録し、答えは叫び出した.
コード#コード#
T 3——点検人数loj 10116
問題解
木の形の配列は裸で問題を書きます~~、書きません
コード#コード#
T 4——[CQOI 2006]簡単問題loj 10117
問題解
高仿T 2,多说したくない
コード#コード#
よし、これだけ辛いことを書いても、たくさん書いても意味がないじゃないか.
木の配列の問題をする前に、3つの板の問題をする必要があります.
ボード1——単点修正、区間照会
板子题就不写题解了哈
コード#コード#
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
int n,q,a[1000005],c[1000005];
void update(int t,int v)
{
for (int x=t; x<=n; x+=x&-x) c[x]+=v;
}
int getsum(int t)
{
int ans=0;
for (int x=t; x; x-=x&-x) ans+=c[x];
return ans;
}
signed main()
{
scanf("%lld%lld",&n,&q);
for (int i=1; i<=n; i++) scanf("%lld",&a[i]),update(i,a[i]);
for (int i=1; i<=q; i++){
int x,l,r;
scanf("%lld%lld%lld",&x,&l,&r);
if (x==1) update(l,r);
if (x==2) printf("%lld
",getsum(r)-getsum(l-1));
}
return 0;
}
板子題2——区間修正、単点照会
コード#コード#
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
int n,q,a[1000005],c[1000005];
void update(int x,int v)
{
for (; x<=n; x+=x&-x) c[x]+=v;
}
int getsum(int x)
{
int sum=0;
for (; x>0; x-=x&-x) sum+=c[x];
return sum;
}
signed main()
{
scanf("%lld",&n);
scanf("%lld",&q);
int last=0;
for (int i=1; i<=n; i++) {scanf("%lld",&a[i]); update(i,a[i]-last); last=a[i];}
for (int i=1; i<=q; i++){
int f;
scanf("%lld",&f);
if (f==1) {
int x,y,v;
scanf("%lld%lld%lld",&x,&y,&v);
update(x,v); update(y+1,-v);
}
else{
long long ans; int x;
scanf("%lld",&x);
ans=getsum(x);
printf("%lld
",ans);
}
}
}
板子題3——区間修正、区間照会
コード#コード#
#include
#include
#define ll long long
using namespace std;
int n,q;
ll a[1000005],c1[1000005],c2[1000005];
void update(int x,int v)
{
for (int X=x; X<=n;X+=X&-X) c1[X]+=v,c2[X]+=(ll)v*x;
}
ll getsum(int x)
{
ll sum=0;
for (int X=x; X>0; X-=X&-X) sum+=(ll)(x+1)*c1[X]-c2[X];
return sum;
}
int main()
{
scanf("%d%d",&n,&q);
for (int i=1; i<=n; i++) scanf("%lld",&a[i]),a[i]+=a[i-1];
while (q--){
char st[3];
scanf("%s",st);
if (st[0]=='2'){
int x,y;
scanf("%d%d",&x,&y);
printf("%lld
",getsum(y)-getsum(x-1)+a[y]-a[x-1]);
}
else {
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
update(x,v); update(y+1,-v);
}
}
return 0;
}
正式に問題を塗ります!!
T 1——星を数えるUral 1028/loj 10114
問題解
入力時にテーマが並べ替えられているため、並べられたデータであればy軸とは関係なく、現在の星の級数は、その星の前のすべてのx軸がその星のx軸の大きさに等しい数の和より小さいと推理されている.これからは楽しくコードをコードできます~~~
コード#コード#
#include
#include
#include
#include
#include
#include
using namespace std;
int n,a[1000005],c[1000005],ans[1000005];
void update(int x,int v)
{
for (; x<=40000; x+=x&-x) c[x]+=v;
}
int getsum(int x)
{
int ans=0;
for (; x; x-=x&-x) ans+=c[x];
return ans;
}
int main()
{
scanf("%d",&n);
for (int i=1; i<=n; i++){
int x,y;
scanf("%d%d",&x,&y);
x++;
ans[getsum(x)]++;
update(x,1);
}
for (int i=1; i<=n; i++) printf("%d
",ans[i-1]);
return 0;
}
T 2——校門外の木vijos 1148loj 10115
問題解
この問題を括弧シーケンスに変換し、区間に1つの木を植えることはlの位置に1つを加えることに相当する(,r rの位置に1つの右括弧を加える.2つの木状配列を維持し、1つは左括弧を記録し、1つは右括弧を記録し、答えは叫び出した.
コード#コード#
#include
#include
#include
#include
#include
#include
using namespace std;
int n,m,c[1000005][2],a[1000005];
void update(int x,int y,int t)
{
for (; x<=n; x+=x&-x) c[x][t]+=y;
}
int getsum(int x,int t)
{
int ans=0;
for (; x; x-=x&-x) ans+=c[x][t];
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1; i<=m; i++){
int x,l,r;
scanf("%d%d%d",&x,&l,&r);
if (x==1) update(l,1,0),update(r,1,1);
if (x==2) printf("%d
",getsum(r,0)-getsum(l-1,1));
}
return 0;
}
T 3——点検人数loj 10116
問題解
木の形の配列は裸で問題を書きます~~、書きません
コード#コード#
#include
#include
#include
#include
#include
#include
using namespace std;
int n,k,c[1000005];
char ch[1005];
void update(int x,int y)
{
for (; x<=n; x+=x&-x) c[x]+=y;
}
int getsum(int x)
{
int ans=0;
for (; x; x-=x&-x) ans+=c[x];
return ans;
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1; i<=k; i++){
scanf("%s",ch);
if (ch[0]=='A') {
int x;
scanf("%d",&x);
printf("%d
",getsum(x));
}
if (ch[0]=='B'){
int x,y;
scanf("%d%d",&x,&y);
update(x,y);
}
if (ch[0]=='C'){
int x,y;
scanf("%d%d",&x,&y);
update(x,-y);
}
}
return 0;
}
T 4——[CQOI 2006]簡単問題loj 10117
問題解
高仿T 2,多说したくない
コード#コード#
#include
#include
#include
#include
#include
#include
using namespace std;
int n,m,c[1000005][2];
void update(int x,int y,int t)
{
for (; x<=n; x+=x&-x) c[x][t]+=y;
}
int getsum(int x,int t)
{
int ans=0;
for (; x; x-=x&-x) ans+=c[x][t];
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1; i<=m; i++){
int x; scanf("%d",&x);
if (x==1) {
int l,r;
scanf("%d%d",&l,&r);
update(l,1,0); update(r,1,1);
}
if (x==2){
int t; scanf("%d",&t);
printf("%d
",(getsum(t,0)-getsum(t-1,1))&1);
}
}
return 0;
}
よし、これだけ辛いことを書いても、たくさん書いても意味がないじゃないか.