标程 爆零专场Orz
A-UVA11297
树套树基础没学过
#include <bits/stdc++.h>
using namespace std;
#define N 505
#define ls o<<1
#define rs o<<1|1
#define def_m int m=(l+r)>>1
const int INF = 0x7fffffff;
int n , q , mx[N*][N*] , mn[N*][N*] , ansmx,ansmn,a[N][N];
void update1D(int o , int l , int r , int y , int ox , int v,int flag)
{
if(l==r){
if(!flag)mx[ox][o] = mn[ox][o] = v;
else{mx[ox][o] = max(mx[ox<<][o],mx[ox<<|][o]) ; mn[ox][o] = min(mn[ox<<][o],mn[ox<<|][o]);}
return ;
}
def_m;
if(m>=y) update1D(ls,l,m,y,ox,v,flag);
else update1D(rs,m+,r,y,ox,v,flag);
mx[ox][o] = max(mx[ox][ls] , mx[ox][rs]);
mn[ox][o] = min(mn[ox][ls] , mn[ox][rs]);
// cout<<ox<<" "<<o<<" "<<l<<" "<<r<<" "<<y<<" "<<v<<endl;
}
void update2D(int o , int l , int r , int x , int y , int v)
{
// cout<<"v: "<<v<<endl;
if(l==r){
update1D(,,n,y,o,v,);
return ;
}
def_m;
if(m>=x) update2D(ls,l,m,x,y,v);
else update2D(rs,m+,r,x,y,v);
update1D(,,n,y,o,v,);
}
void query1D(int o , int l , int r , int s , int t , int ox)
{
if(l>=s&&r<=t){
ansmx=max(ansmx,mx[ox][o]);
// cout<<"in query: "<<ox<<" "<<o<<" "<<s<<" "<<t<<" "<<mx[ox][o]<<" "<<mn[ox][o]<<endl;
ansmn=min(ansmn,mn[ox][o]);
return ;
}
def_m;
if(m>=s) query1D(ls,l,m,s,t,ox);
if(m<t) query1D(rs,m+,r,s,t,ox);
}
void query2D(int o,int l,int r,int sx,int tx,int sy,int ty)
{
if(l>=sx&&r<=tx){
query1D(,,n,sy,ty,o);
return ;
}
def_m;
if(m>=sx) query2D(ls,l,m,sx,tx,sy,ty);
if(m<tx) query2D(rs,m+,r,sx,tx,sy,ty);
}
void build1D(int o , int l , int r , int ox , int x)
{
if(l==r){
if(x>=) mx[ox][o] = mn[ox][o] = a[x][l];
else mx[ox][o] = max(mx[ox<<][o] , mx[ox<<|][o]) , mn[ox][o] = min(mn[ox<<][o] , mn[ox<<|][o]);
return ;
}
def_m;
build1D(ls , l , m , ox , x);
build1D(rs , m+ , r , ox , x);
mx[ox][o] = max(mx[ox][ls] , mx[ox][rs]);
mn[ox][o] = min(mn[ox][ls] , mn[ox][rs]);
}
void build2D(int o , int l , int r , int ly , int ry)
{
if(l==r){
build1D(,,n,o,l);
return ;
}
def_m;
build2D(ls , l , m , ly , ry);
build2D(rs , m+ , r , ly , ry);
build1D( , , n , o , -);
}
int main()
{
// freopen("a.in" , "r" , stdin);
while(~scanf("%d" , &n)){
memset(mx , 0x80 , sizeof(mx));
memset(mn , 0x7f , sizeof(mn));
for(int i= ; i<=n ; i++)
for(int j= ; j<=n ; j++)scanf("%d" , &a[i][j]);
build2D(,,n,,n);
scanf("%d" , &q);
for(int i= ; i<q ; i++){
char op[];
scanf("%s" , op);
if(op[]=='q'){
int x1,y1,x2,y2;
scanf("%d%d%d%d" , &x1,&y1,&x2,&y2);
ansmx = -INF , ansmn=INF;
query2D(,,n,x1,x2,y1,y2);
printf("%d %d\n" , ansmx,ansmn);
}
else{
int x,y,v;
scanf("%d%d%d" , &x,&y,&v);
update2D(,,n,x,y,v);
}
}
}
return ;
B-HDU-2855
学长标程
#include "bits/stdc++.h"
using namespace std;
inline int read() {
int x = 0;
bool f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
if (f) return x;
return 0 - x;
}
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define ll long long
const int maxn = (1 << 21) + 10;
const double PI = acos(-1.0);
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int m;
/**
因为 ans = (C[n][0]*F[0] + C[n][1]*F[1] + ... + C[n][n]*F[n])
设矩 阵A= | 1 1 |
| 1 0 | 即斐波那契数列递推式的特征矩阵
然后 另 ans = (C[n][0]*(A^0) + C[n][1]*(A^1) + ... + C[n][n]*(A^n))
根据二项式定理另矩阵D = (E + A)^n 矩阵快速幂即可。
D[0][1] 或者 D[1][0]就为所求答案。
没想到上面那个怎么办?
打一个表,或者打出前几项你们就会发现和斐波那契数列的关系
记 ans = s(n)
s(0) = F(0)
s(1) = F(1)
s(2) = F(4)
...
s(n) = F(2*n)
矩阵快速幂求斐波那契数列即可。
*/
struct mat {
ll a[21][21];
int n;
void init(int sz) {
n = sz;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) a[i][j] = 0;
}
void matE() {
for (int i = 0; i < n; i++) a[i][i] = 1;
}
inline mat operator+(const mat &T) const {
mat res;
res.init(n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
res.a[i][j] = (a[i][j] + T.a[i][j] + m) % m;
return res;
}
inline mat operator-(const mat &T) const {
mat res;
res.init(n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
res.a[i][j] = (a[i][j] - T.a[i][j] + m) % m;
return res;
}
inline mat operator*(const mat &T) const {
mat res;
ll r;
res.init(n);
for (int i = 0; i < n; ++i)
for (int k = 0; k < n; ++k) {
r = a[i][k];
for (int j = 0; j < n; ++j)
res.a[i][j] += T.a[k][j] * r,
res.a[i][j] %= m;
}
return res;
}
inline mat operator^(ll x) const {
mat res, bas;
res.init(n);
bas.init(n);
for (int i = 0; i < n; ++i) res.a[i][i] = 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) bas.a[i][j] = a[i][j];
while (x) {
if (x & 1) res = res * bas;
bas = bas * bas;
x >>= 1;
}
return res;
}
} p;
int main() {
int T, n;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
p.init(2);
p.a[0][0] = 2, p.a[0][1] = 1;
p.a[1][0] = 1, p.a[1][1] = 1;
mat res = (p ^ n);
ll ans = res.a[1][0];
// ans %= mod;
cout << ans << endl;
}
return 0;
}
/*
将第一棵树用dfs序hash,遍历第二棵树时将对应的子树区间整体加一,每访问一个节点查询覆盖次数
覆盖次数合即为所求点对。
*/
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<vector>
#include<iostream>
#include<math.h>
#include <map>
#include<set>
#define ll long long
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs ((k<<1)|1)
using namespace std;
const int maxn=2e6+10;
const int inf=1e9;
int tree[maxn];
int lowbit(int x){return x&(-x);}
void add(int x,int va){
while(x<maxn){
tree[x]+=va;
x+=lowbit(x);
}
}
int sum(int x){
int sum=0;
while(x>0){
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
ll ans;
int in[maxn],out[maxn],tot,head[maxn],head1[maxn];
struct node{
int to,nex;
}side[maxn*2],side1[maxn*2];
void ad(int u,int v){
side[tot]={v,head[u]};
head[u]=tot++;
side[tot]={u,head[v]};
head[v]=tot++;
}
void ad1(int u,int v){
side1[tot]={v,head1[u]};
head1[u]=tot++;
side1[tot]={u,head1[v]};
head1[v]=tot++;
}
void dfs(int now,int f){
in[now]=++tot;
for(int i=head[now];i!=-1;i=side[i].nex){
int v=side[i].to;
if(v==f) continue;
dfs(v,now);
}
out[now]=tot;
}
void dfs1(int now,int f){
ans+=sum(in[now]);
add(in[now],1),add(out[now]+1,-1);
for(int i=head1[now];i!=-1;i=side1[i].nex){
int v=side1[i].to;
if(v==f) continue;
dfs1(v,now);
}
add(in[now],-1),add(out[now]+1,1);
}
int main( ){
int n;
scanf("%d",&n);
for(int a=1;a<=n;a++) head[a]=head1[a]=-1;
for(int a=1;a<n;a++){
int u,v;
scanf("%d%d",&u,&v);
ad(u,v);
}
tot=0;
for(int a=1;a<n;a++){
int u,v;
scanf("%d%d",&u,&v);
ad1(u,v);
}
tot=0;
ans=0;
dfs(1,1);
dfs1(1,1);
printf("%lld\n",ans);
}
D-HDU-4578
pushdown的顺序很重要!!!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=5*1e5+50;
const int inf=0x3f3f3f3f;
const int MOD=10007;
ll lazy_1[maxn];
ll lazy_2[maxn];
ll lazy_3[maxn];
struct node
{
ll maxx_1,maxx_2,maxx_3;
int sum;
}tree[maxn];
void pushup(int k)
{
tree[k].maxx_1=(tree[k*2].maxx_1+tree[k*2+1].maxx_1)%MOD;
tree[k].maxx_2=(tree[k*2].maxx_2+tree[k*2+1].maxx_2)%MOD;
tree[k].maxx_3=(tree[k*2].maxx_3+tree[k*2+1].maxx_3)%MOD;
}
void pushdown(int k)
{
if(lazy_3[k])
{
lazy_1[k*2]=lazy_1[k*2+1]=0;
lazy_2[k*2]=lazy_2[k*2+1]=1;
tree[k*2].maxx_1=(lazy_3[k]*tree[k*2].sum)%MOD;
tree[k*2].maxx_2=((lazy_3[k]*tree[k*2].sum)%MOD*lazy_3[k])%MOD;
tree[k*2].maxx_3=(((lazy_3[k]*tree[k*2].sum)%MOD*lazy_3[k])%MOD*lazy_3[k])%MOD;
tree[k*2+1].maxx_1=(lazy_3[k]*tree[k*2+1].sum)%MOD;
tree[k*2+1].maxx_2=((lazy_3[k]*tree[k*2+1].sum)%MOD*lazy_3[k])%MOD;
tree[k*2+1].maxx_3=(((lazy_3[k]*tree[k*2+1].sum)%MOD*lazy_3[k])%MOD*lazy_3[k])%MOD;
lazy_3[k*2]=lazy_3[k];
lazy_3[k*2+1]=lazy_3[k];
lazy_3[k]=0;
}
if(lazy_2[k]!=1)
{
if(lazy_1[k*2])
lazy_1[k*2]=(lazy_1[k*2]*lazy_2[k])%MOD;
tree[k*2].maxx_1=(tree[k*2].maxx_1*lazy_2[k])%MOD;
tree[k*2].maxx_2=((tree[k*2].maxx_2*lazy_2[k])%MOD*lazy_2[k])%MOD;
tree[k*2].maxx_3=(((tree[k*2].maxx_3*lazy_2[k])%MOD*lazy_2[k])%MOD*lazy_2[k])%MOD;
if(lazy_1[k*2+1])
lazy_1[k*2+1]=(lazy_1[k*2+1]*lazy_2[k])%MOD;
tree[k*2+1].maxx_1=(tree[k*2+1].maxx_1*lazy_2[k])%MOD;
tree[k*2+1].maxx_2=((tree[k*2+1].maxx_2*lazy_2[k])%MOD*lazy_2[k])%MOD;
tree[k*2+1].maxx_3=(((tree[k*2+1].maxx_3*lazy_2[k])%MOD*lazy_2[k])%MOD*lazy_2[k])%MOD;
lazy_2[k*2]=(lazy_2[k*2]*lazy_2[k])%MOD;
lazy_2[k*2+1]=(lazy_2[k*2+1]*lazy_2[k])%MOD;
lazy_2[k]=1;
}
if(lazy_1[k])
{
tree[k*2].maxx_3=(tree[k*2].maxx_3+((lazy_1[k]*lazy_1[k])%MOD*lazy_1[k])%MOD*tree[k*2].sum%MOD+3*lazy_1[k]*(tree[k*2].maxx_2+tree[k*2].maxx_1*lazy_1[k]%MOD))%MOD;
tree[k*2].maxx_2=(tree[k*2].maxx_2+((lazy_1[k]*lazy_1[k])%MOD*tree[k*2].sum)%MOD+2*tree[k*2].maxx_1*lazy_1[k])%MOD;
tree[k*2].maxx_1=(tree[k*2].maxx_1+lazy_1[k]*tree[k*2].sum)%MOD;
tree[k*2+1].maxx_3=(tree[k*2+1].maxx_3+((lazy_1[k]*lazy_1[k])%MOD*lazy_1[k])%MOD*tree[k*2+1].sum%MOD+3*lazy_1[k]*(tree[k*2+1].maxx_2+tree[k*2+1].maxx_1*lazy_1[k]%MOD))%MOD;
tree[k*2+1].maxx_2=(tree[k*2+1].maxx_2+((lazy_1[k]*lazy_1[k])%MOD*tree[k*2+1].sum)%MOD+2*tree[k*2+1].maxx_1*lazy_1[k])%MOD;
tree[k*2+1].maxx_1=(tree[k*2+1].maxx_1+lazy_1[k]*tree[k*2+1].sum)%MOD;
lazy_1[k*2]=(lazy_1[k*2]+lazy_1[k])%MOD;
lazy_1[k*2+1]=(lazy_1[k*2+1]+lazy_1[k])%MOD;
lazy_1[k]=0;
}
}
void build(int l,int r,int k)
{
lazy_1[k]=lazy_3[k]=0;
lazy_2[k]=1;
if(l==r)
{
tree[k].sum=1;
tree[k].maxx_1=0;
tree[k].maxx_2=0*0;
tree[k].maxx_3=0*0*0;
return;
}
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
pushup(k);
tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
}
void updata_1(int l,int r,int ll,int rr,int k,int c)
{
if(ll<=l&&rr>=r)
{
lazy_1[k]+=c;
tree[k].maxx_3=(tree[k].maxx_3+((c*c)%MOD*c)%MOD*tree[k].sum%MOD+3*c*(tree[k].maxx_2+tree[k].maxx_1*c%MOD))%MOD;
tree[k].maxx_2=(tree[k].maxx_2+((c*c)%MOD*tree[k].sum)%MOD+2*tree[k].maxx_1*c)%MOD;
tree[k].maxx_1=(tree[k].maxx_1+c*tree[k].sum)%MOD;
return;
}
pushdown(k);
int mid=(l+r)/2;
if(ll<=mid) updata_1(l,mid,ll,rr,k*2,c);
if(rr>mid) updata_1(mid+1,r,ll,rr,k*2+1,c);
pushup(k);
}
void updata_2(int l,int r,int ll,int rr,int k,int c)
{
if(l>=ll&&r<=rr)
{
lazy_2[k]=(lazy_2[k]*c)%MOD;
if(lazy_1[k])
lazy_1[k]=(lazy_1[k]*c)%MOD;
tree[k].maxx_1=(tree[k].maxx_1*c)%MOD;
tree[k].maxx_2=((tree[k].maxx_2*c)%MOD*c)%MOD;
tree[k].maxx_3=(((tree[k].maxx_3*c)%MOD*c)%MOD*c)%MOD;
return;
}
pushdown(k);
int mid=(l+r)/2;
if(ll<=mid) updata_2(l,mid,ll,rr,k*2,c);
if(rr>mid) updata_2(mid+1,r,ll,rr,k*2+1,c);
pushup(k);
}
void updata_3(int l,int r,int ll,int rr,int k,int c)
{
if(l>=ll&&r<=rr)
{
lazy_3[k]=c%MOD;
lazy_1[k]=0;
lazy_2[k]=1;
tree[k].maxx_1=(c*tree[k].sum)%MOD;
tree[k].maxx_2=((c*tree[k].sum)%MOD*c)%MOD;
tree[k].maxx_3=(((c*tree[k].sum)%MOD*c)%MOD*c)%MOD;
return;
}
pushdown(k);
int mid=(l+r)/2;
if(ll<=mid) updata_3(l,mid,ll,rr,k*2,c);
if(rr>mid) updata_3(mid+1,r,ll,rr,k*2+1,c);
pushup(k);
}
int FIND_1(int l,int r,int ll,int rr,int k)
{
if(l>=ll&&r<=rr)
{
return tree[k].maxx_1;
}
pushdown(k);
int ans=0;
int mid=(l+r)/2;
if(ll<=mid) ans+=FIND_1(l,mid,ll,rr,k*2);
if(rr>mid) ans+=FIND_1(mid+1,r,ll,rr,k*2+1);
return ans%MOD;
}
int FIND_2(int l,int r,int ll,int rr,int k)
{
if(l>=ll&&r<=rr)
{
return tree[k].maxx_2;
}
pushdown(k);
int ans=0;
int mid=(l+r)/2;
if(ll<=mid) ans+=FIND_2(l,mid,ll,rr,k*2);
if(rr>mid) ans+=FIND_2(mid+1,r,ll,rr,k*2+1);
return ans%MOD;
}
int FIND_3(int l,int r,int ll,int rr,int k)
{
if(l>=ll&&r<=rr)
{
return tree[k].maxx_3;
}
pushdown(k);
int ans=0;
int mid=(l+r)/2;
if(ll<=mid) ans=(ans+FIND_3(l,mid,ll,rr,k*2))%MOD;
if(rr>mid) ans=(ans+FIND_3(mid+1,r,ll,rr,k*2+1))%MOD;
return ans;
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF&&n+m)
{
build(1,n,1);
while(m--)
{
int op,x,y,c;
scanf("%d %d %d %d",&op,&x,&y,&c);
if(op==1)
{
updata_1(1,n,x,y,1,c);
}
else if(op==2)
{
updata_2(1,n,x,y,1,c);
}
else if(op==3)
{
updata_3(1,n,x,y,1,c);
}
else
{
if(c==1)
printf("%d\n",FIND_1(1,n,x,y,1));
else if(c==2)
printf("%d\n",FIND_2(1,n,x,y,1));
else
printf("%d\n",FIND_3(1,n,x,y,1));
}
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
#define lowbit(x) ((x)&(-x))
pair<ll, ll> p[maxn], x[maxn], w[maxn];
ll cnt[maxn], dis[maxn];
ll sum(ll *bit, int x) {
ll res = 0;
for (int i = x; i > 0; i -= lowbit(i))
res += bit[i];
return res;
}
ll sum(ll *bit, int from, int to) {
return sum(bit, to - 1) - sum(bit, from - 1);
}
void update(ll *bit, int x, ll y) {
for (int i = x; i <= maxn; i += lowbit(i))
bit[i] += y;
}
bool cmp(pair<ll, ll> a, pair<ll, ll> b) {
return a.second > b.second;
}
int main() {
int n;
while (~scanf("%d", &n)) {
//用pair建立x坐标与员工编号k的关系,评分w与员工编号k的关系,之后分别按照x坐标与评分w进行排序
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &x[i].first, &w[i].first);
x[i].second = w[i].second = i;
}
sort(x + 1, x + n + 1);
sort(w + 1, w + n + 1);
//对x坐标或评分w相同的员工们进行处理,并得到对应的rank值
ll tmpx = x[1].first, tmpw = w[1].first, ans = 0;
x[1].first = w[1].first = 1;
for (int i = 2; i <= n; i++) {
if (x[i].first == tmpx)
x[i].first = x[i - 1].first;
else {
tmpx = x[i].first;
x[i].first = i;
}
if (w[i].first == tmpw)
w[i].first = w[i - 1].first;
else {
tmpw = w[i].first;
w[i].first = i;
}
}
//用p数组建立员工i的rank(xi)和rank(wi)之间的关系
for (int i = 1; i <= n; i++) {
p[x[i].second].first = x[i].first;
p[w[i].second].second = w[i].first;
}
//按照评分降序排列
sort(p + 1, p + 1 + n, cmp);
//维护两个树状数组
memset(cnt, 0, sizeof(cnt));
memset(dis, 0, sizeof(dis));
//遍历p[],每多访问一个员工,就计算它与之前所有员工的关系f的和
//因为rua的值是min(wi, wj)
//所以对评分降序排列,访问到当前员工时,他与前面所有员工的rua,都是他的w
//所以每次新遍历到一个员工,就用他的w,乘以他与之前所有员工的dis的和即可
for (int i = 1; i <= n; i++) {
ll now_x = p[i].first, now_w = p[i].second;//当前员工的x坐标与评分w
ll left = sum(cnt, 1, now_x), right = sum(cnt, now_x + 1, maxn);//左边员工数量和右边员工的数量
//因为按高度排序,所以已经访问过的员工,会分布在当前员工的左右两侧,所以要分开计算
//左边所有访问过的员工,与当前员工的dis和,就是左边员工的数量 * 当前员工的rank(x) - sum(左边员工的rank(x))
//右边员工同理
ans += now_w * (left * now_x - sum(dis, 1, now_x) + sum(dis, now_x + 1, maxn) - right * now_x);
update(cnt, now_x, 1);//更新数量
update(dis, now_x, now_x);//更新坐标
}
printf("%lld\n", ans);
}
return 0;
}
爆零了有什么好说的,菜是原罪,努力刷题吧
赛况记录
爆零