请问为什么线段树+树状数组全部TLE

线段树求区间第k小,树状数组将每个点拆成询问后处理区间小于x的值全部TLE

/*
 * Author: xiaohei_AWM
 * Date: 5.24
 * Mutto: Face to the weakness, expect for the strength.
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<set>
#include<queue>
#include<utility>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
using namespace std;
#define reg register
#define endfile fclose(stdin);fclose(stdout);
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
namespace IO{
    char buf[1<<15],*S,*T;
    inline char gc(){
        if (S==T){
            T=(S=buf)+fread(buf,1,1<<15,stdin);
            if (S==T)return EOF;
        }
        return *S++;
    }
    inline int read(){
        reg int x;reg bool f;reg char c;
        for(f=0;(c=gc())<'0'||c>'9';f=c=='-');
        for(x=c^'0';(c=gc())>='0'&&c<='9';x=(x<<3)+(x<<1)+(c^'0'));
        return f?-x:x;
    }
    inline ll readll(){
        reg ll x;reg bool f;reg char c;
        for(f=0;(c=gc())<'0'||c>'9';f=c=='-');
        for(x=c^'0';(c=gc())>='0'&&c<='9';x=(x<<3)+(x<<1)+(c^'0'));
        return f?-x:x;
    }
}
using namespace IO;
const int maxn = 1e5 + 10;
int n, m, k, s[maxn];
ll ans, sum, c[maxn], temp[maxn], kth, kthid;
struct Element{
    int id;
    ll val;
    bool operator<(const Element &v)const{
        if(val == v.val)
            return id < v.id;
        return val < v.val;
    }
} a[maxn];
struct Query{
    int l, r, id;
    ll val;
} b[maxn];
inline int lowbit(int x){
    return x & -x;
}
void add(int pos, ll val){
    for(int i = pos; i <= n; i += lowbit(i))
        c[i] += val;
}
ll queryS(int pos){
    ll res = 0;
    for(int i = pos; i >= 1; i -= lowbit(i))
        res += c[i];
    return res;
}
bool cmp2(Query u, Query v){
    return u.val < v.val;
}
vector<int>date[maxn*4+5];  //存线段树节点信息
void build(int ro,int l,int r)
{
  if(l == r)
  {
    date[ro].push_back(-1e7);             //乱塞一个数(0号位置)
    date[ro].push_back(s[l]); return;
  }
  int mid = (l+r)>>1;
  build(ro<<1,l,mid);
  build(ro<<1|1,mid+1,r);

  //这一部分类似于归并排序(应该说就是一样的),保证时间复杂度。
  int size1 = date[ro<<1].size()-1;
  int size2 = date[ro<<1|1].size()-1;
  int i = 1,j = 1;
  date[ro].push_back(-1e7);
  while(i<=size1 && j<=size2)
    {
      if(date[ro<<1][i]>date[ro<<1|1][j])date[ro].push_back(date[ro<<1|1][j++]);
      else date[ro].push_back(date[ro<<1][i++]);
    }
  while(i<=size1)date[ro].push_back(date[ro<<1][i++]);
  while(j<=size2)date[ro].push_back(date[ro<<1|1][j++]);
  return;

}

//二分查找完全包含的区间中小于等于R的数的个数
int low_bound(int ro,int target)
{
  int L,R,res;
  L =1 ; R = date[ro].size()-1;res = 0;
  while(L<=R)
    {
      int mid = (L+R)>>1;
      if(date[ro][mid]<=target){res = mid; L = mid + 1;}
      else R = mid - 1;
    }
  return res;
}

//线段树查询区间内小于等于R的数的个数
//tl--target L ;  tr--target R;  l--now L;  r--now R 。
int query(int ro,int l,int r,int tl,int tr,int K)
{
  if(tr<l || tl>r)return 0;   //没有交集
  else if(tl<=l && r<=tr)     //完全包含
    {
      int temp_num = low_bound(ro,K);
      return temp_num;
    }
  else             //有交集但不完全包含,递归查找左右子树
    {
      int mid = (l + r)>>1;
      int temp1 = query(ro<<1,l,mid,tl,tr,K);
      int temp2 = query(ro<<1|1,mid+1,r,tl,tr,K);
      return (temp1+temp2);     //合并答案
    }
}

//二分查找目标值R,二分出值R后再用线段树进行验证
int search(int l,int r,int k)
{
  int L,R,RES,NUM;
  L = -1000000007; R = 1000000007;
  while(L<=R)
    {
      int mid = (L+R)>>1;
      NUM = query(1,1,n,l,r,mid);  //RES不断向下逼近,保证精确性。
      if(NUM >= k){RES = mid ; R = mid-1;}
      else L = mid+1;
    }
  return RES;
}

int main(){
    cin >> n >> m >>k;
    for(int i = 1; i <= n; i++)
        cin >> s[i];
    build(1, 1, n);
    for(int i = 1; i <= n-m+1; i++){
        a[i].val = search(i, i+m, k);
        a[i].id = i;
    }
    int LIM = n-m+1;
    for(int i = 1; i <= n; i++){
        b[i].l = max(1, i - m + 1);
        b[i].r = min(LIM, i);
        b[i].val = s[i];
        b[i].id = i;
    }
    sort(a+1, a+1+LIM);
    sort(b+1, b+1+n, cmp2);
    int cnt = 1;
    for(int i = 1; i <= n; i++){
        while(k <= LIM && a[k].val <= b[i].val){
            add(a[k].id, 1);
            k++;
        }
        ans += (ll)(queryS(b[i].r) - queryS(b[i].l-1)) * s[b[i].id];
    }
    ans -= b[n].val;
    cout << ans << endl;
    return 0;
}
全部评论
已解决主要TLE问题:现在求帮卡常 /* * Author: xiaohei_AWM * Date: 5.24 * Mutto: Face to the weakness, expect for the strength. */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<ctime> #include<set> #include<queue> #include<utility> #include<functional> #include<cmath> #include<vector> #include<assert.h> using namespace std; #define reg register #define endfile fclose(stdin);fclose(stdout); typedef long long ll; typedef unsigned long long ull; typedef double db; typedef std::pair<int,int> pii; typedef std::pair<ll,ll> pll; namespace IO{ char buf[1<<15],*S,*T; inline char gc(){ if (S==T){ T=(S=buf)+fread(buf,1,1<<15,stdin); if (S==T)return EOF; } return *S++; } inline int read(){ reg int x;reg bool f;reg char c; for(f=0;(c=gc())<'0'||c>'9';f=c=='-'); for(x=c^'0';(c=gc())>='0'&&c<='9';x=(x<<3)+(x<<1)+(c^'0')); return f?-x:x; } inline ll readll(){ reg ll x;reg bool f;reg char c; for(f=0;(c=gc())<'0'||c>'9';f=c=='-'); for(x=c^'0';(c=gc())>='0'&&c<='9';x=(x<<3)+(x<<1)+(c^'0')); return f?-x:x; } } using namespace IO; const int maxn = 1e5 + 10; int n, m, k, s[maxn]; ll ans, sum, c[maxn], temp[maxn], kth, kthid; struct Element{ int id; ll val; bool operator<(const Element &v)const{ if(val == v.val) return id < v.id; return val > v.val; } } a[maxn]; struct Query{ int l, r, id; ll val; } b[maxn]; inline int lowbit(int x){ return x & -x; } void add(int pos, ll val){ for(int i = pos; i <= n; i += lowbit(i)) c[i] += val; } ll queryS(int pos){ ll res = 0; for(int i = pos; i; i -= lowbit(i)) res += c[i]; return res; } bool cmp2(Query u, Query v){ return u.val > v.val; } vector<int>date[maxn*4+5]; //存线段树节点信息 void build(int ro,int l,int r) { if(l == r) { date[ro].push_back(-1e7); //乱塞一个数(0号位置) date[ro].push_back(s[l]); return; } int mid = (l+r)>>1; build(ro<<1,l,mid); build(ro<<1|1,mid+1,r); //这一部分类似于归并排序(应该说就是一样的),保证时间复杂度。 int size1 = date[ro<<1].size()-1; int size2 = date[ro<<1|1].size()-1; int i = 1,j = 1; date[ro].push_back(-1e7); while(i<=size1 && j<=size2) { if(date[ro<<1][i]>date[ro<<1|1][j])date[ro].push_back(date[ro<<1|1][j++]); else date[ro].push_back(date[ro<<1][i++]); } while(i<=size1)date[ro].push_back(date[ro<<1][i++]); while(j<=size2)date[ro].push_back(date[ro<<1|1][j++]); return; } //二分查找完全包含的区间中小于等于R的数的个数 int low_bound(int ro,int target) { int L,R,res; L =1 ; R = date[ro].size()-1;res = 0; while(L<=R) { int mid = (L+R)>>1; if(date[ro][mid]<=target){res = mid; L = mid + 1;} else R = mid - 1; } return res; } //线段树查询区间内小于等于R的数的个数 //tl--target L ; tr--target R; l--now L; r--now R 。 int query(int ro,int l,int r,int tl,int tr,int K) { if(tr<l || tl>r)return 0; //没有交集 else if(tl<=l && r<=tr) //完全包含 { int temp_num = low_bound(ro,K); return temp_num; } else //有交集但不完全包含,递归查找左右子树 { int mid = (l + r)>>1; int temp1 = query(ro<<1,l,mid,tl,tr,K); int temp2 = query(ro<<1|1,mid+1,r,tl,tr,K); return (temp1+temp2); //合并答案 } } //二分查找目标值R,二分出值R后再用线段树进行验证 int search(int l,int r,int k) { int L,R,RES,NUM; L = 0; R = maxn; while(L<=R) { int mid = (L+R)>>1; NUM = query(1,1,n,l,r,mid); //RES不断向下逼近,保证精确性。 if(NUM >= k){RES = mid ; R = mid-1;} else L = mid+1; } return RES; } bool cmpx(Element x, Element y){ if(x.val == y.val) return x.id < y.id; return x.val < y.val; } int main(){ n = read(), m = read(), k = read(); for(int i = 1; i <= n; i++) a[i].val = temp[i] = readll(), a[i].id = i; sort(a+1, a+1+n, cmpx); for(int i = 1; i <= n; i++) s[a[i].id] = i; build(1, 1, n); for(int i = 1; i <= n-m+1; i++){ a[i].val = search(i, i+m-1, k); a[i].id = i; } int LIM = n-m+1; for(int i = 1; i <= n; i++){ b[i].l = max(1, i - m + 1); b[i].r = min(LIM, i); b[i].val = s[i]; b[i].id = i; } sort(a+1, a+1+LIM); sort(b+1, b+1+n, cmp2); int cnt = 1; for(int i = 1; i <= n; i++){ while(cnt <= LIM && a[cnt].val >= b[i].val){ add(a[cnt].id, 1); cnt++; } int num = (queryS(b[i].r) - queryS(b[i].l-1)); ans += (ll)(queryS(b[i].r) - queryS(b[i].l-1)) * temp[b[i].id]; } cout << ans << endl; return 0; }
点赞 回复 分享
发布于 2019-05-24 22:54

相关推荐

秋招进行到现在终于能写总结了。完全没想到战线会拉这么长,过程会如此狼狈,不过更应该怪自己太菜了。好在所有的运气都用在了最后,也是有个去处。背景:双2本硕科班,无竞赛,本科一段研究所实习,硕士一段大厂暑期实习但无转正。技术栈是C++&nbsp;&amp;&nbsp;Golang,实习是客户端音视频(而且是鸿蒙端开发),简历两个C++项目一个Golang项目。主要投递岗位:后端,cpp软开,游戏服务端,测开,以及一些不拘泥于Java的岗位。从8月起总共投递123家公司,笔试数不清了,约面大约30家。offer/oc/意向:友塔游戏(第一个offer,面试体验很好,就是给钱好少南瑞继保(计算机科班点击就送(限男生),不...
乡土丁真真:佬很厉害,羡慕~虽然我还没有到校招的时候,也想讲一下自己的看法:我觉得不是CPP的问题,佬的背书双2,技术栈加了GO,有两段实习。投了123,面了30.拿到11个offer。这个数据已经很耀眼了。这不也是CPP带来的吗?当然也不止是CPP。至少来说在这个方向努力过的也会有好的结果和选择。同等学历和项目选java就会有更好的吗?我个人持疑问态度。当然CPP在方向选择上确实让人头大,但是我觉得能上岸,至于最后做什么方向,在我看来并不重要。至于CPP特殊,有岗位方向的随机性,java不是不挑方向,只是没得选而已。也希望自己以后校招的时候能offer满满
点赞 评论 收藏
分享
牛客737698141号:他们可以看到在线简历的。。。估计不合适直接就拒了
点赞 评论 收藏
分享
寿命齿轮:实习就一段还拉了,项目一看就不是手搓,学历也拉了,技术栈看着倒是挺好,就是不知道面试表现能咋样。 不过现在才大三,争取搞两端大厂实习,或者一个纯个人项目+一段大厂,感觉秋招还是未来可期。
投递美团等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务